summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--.gitignore36
-rw-r--r--COPYING19
-rw-r--r--CalleeDlg.cpp89
-rw-r--r--CalleeDlg.h40
-rw-r--r--ColorButton.cpp92
-rw-r--r--ColorButton.h47
-rw-r--r--FontsPage.cpp333
-rw-r--r--FontsPage.h87
-rw-r--r--GeneralPage.cpp100
-rw-r--r--GeneralPage.h42
-rw-r--r--KTAGS12
-rw-r--r--README33
-rw-r--r--SecretaryPage.cpp116
-rw-r--r--SecretaryPage.h59
-rw-r--r--SoundsPage.cpp148
-rw-r--r--SoundsPage.h58
-rw-r--r--T42.clw367
-rw-r--r--T42.cpp468
-rw-r--r--T42.h83
-rw-r--r--T42.mak1691
-rw-r--r--T42.rc837
-rw-r--r--T42AnnounceDlg.cpp144
-rw-r--r--T42AnnounceDlg.h55
-rw-r--r--T42CallLog.h53
-rw-r--r--T42Dlg.cpp1251
-rw-r--r--T42Dlg.h159
-rw-r--r--T42Document.cpp181
-rw-r--r--T42Document.h81
-rw-r--r--T42Frame.cpp1212
-rw-r--r--T42Frame.h169
-rw-r--r--T42Secretary.cpp121
-rw-r--r--T42Secretary.h17
-rw-r--r--T42View.cpp703
-rw-r--r--T42View.h220
-rw-r--r--help/T42.cnt16
-rw-r--r--help/T42.hpj31
-rw-r--r--help/T42.rtf194
-rw-r--r--help/T42.xml183
-rw-r--r--help/announce.bmpbin0 -> 168390 bytes
-rw-r--r--help/invite.bmpbin0 -> 148374 bytes
-rw-r--r--install/custom.rch10
-rw-r--r--install/install.cpp68
-rw-r--r--install/install.rc182
-rw-r--r--install/resource.h24
-rw-r--r--makehelp.bat34
-rw-r--r--res/IDR_FLIP.icobin0 -> 4710 bytes
-rw-r--r--res/IDR_FULL.icobin0 -> 4710 bytes
-rw-r--r--res/IDR_T42F.icobin0 -> 4710 bytes
-rw-r--r--res/T42-beep.wavbin0 -> 848 bytes
-rw-r--r--res/T42-boiling.wavbin0 -> 9644 bytes
-rw-r--r--res/T42-whistle.wavbin0 -> 7736 bytes
-rw-r--r--res/T42.icobin0 -> 4710 bytes
-rw-r--r--res/T42.rc213
-rw-r--r--res/T42calln.icobin0 -> 1078 bytes
-rw-r--r--res/T42callp.icobin0 -> 1078 bytes
-rw-r--r--res/fullcup.icobin0 -> 4710 bytes
-rw-r--r--resource.h200
-rw-r--r--shared-code/BTreendex.h595
-rw-r--r--shared-code/BellsNWhistles.h146
-rw-r--r--shared-code/BitSet.h105
-rw-r--r--shared-code/Dynamide.h443
-rw-r--r--shared-code/FindIFace.h125
-rw-r--r--shared-code/LRUCache.h113
-rw-r--r--shared-code/RegEx.cpp1697
-rw-r--r--shared-code/RegEx.h158
-rw-r--r--shared-code/SNMPExtDll.h252
-rw-r--r--shared-code/SNMPOIDs.h221
-rw-r--r--shared-code/SNMPeer.h286
-rw-r--r--shared-code/install.h370
-rw-r--r--shared-code/ip_icmp.h91
-rw-r--r--shared-code/kHelpers.h159
-rw-r--r--shared-code/kICMP.cpp300
-rw-r--r--shared-code/kICMP.h80
-rw-r--r--shared-code/kinhelp.xsl250
-rw-r--r--shared-code/ms_icmp.h77
-rw-r--r--shared-data/browse-icon.icobin0 -> 1078 bytes
-rw-r--r--shared-data/install-icon.icobin0 -> 2998 bytes
-rw-r--r--shared-data/klever-background.bmpbin0 -> 2578 bytes
-rw-r--r--shared-data/play-icon.icobin0 -> 1078 bytes
-rw-r--r--stdafx.cpp6
-rw-r--r--stdafx.h70
-rw-r--r--talkd.h47
82 files changed, 15669 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..340de8d
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,36 @@
+
+# /
+/Debug
+/Release
+/Releast
+/debug
+/release
+/releast
+/DEBUG
+/RELEASE
+/RELEAST
+/*.mdp
+/*.ncb
+/*.aps
+/redist
+
+# /help/
+/help/T42.HLP
+/help/T42.LOG
+/help/T42.hm
+/help/T42.GID
+
+# /install/
+/install/debug
+/install/pure
+/install/canned
+/install/static
+/install/Debug
+/install/Pure
+/install/Canned
+/install/Static
+/install/DEBUG
+/install/PURE
+/install/CANNED
+/install/STATIC
+/install/*.aps
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..997e508
--- a/dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 1998, 2002 Klever Group (http://www.klever.net/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/CalleeDlg.cpp b/CalleeDlg.cpp
new file mode 100644
index 0000000..971781e
--- a/dev/null
+++ b/CalleeDlg.cpp
@@ -0,0 +1,89 @@
+// CalleeDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "CalleeDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CCalleeDlg dialog
+
+
+CCalleeDlg::CCalleeDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CCalleeDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CCalleeDlg)
+ m_Callee = _T("");
+ m_Caller = _T("");
+ m_TTY = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CCalleeDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CCalleeDlg)
+ DDX_Control(pDX, IDC_CALLER, m_CallerCtl);
+ DDX_Control(pDX, IDC_CALLEE, m_CalleeCtl);
+ DDX_Text(pDX, IDC_CALLEE, m_Callee);
+ DDX_CBString(pDX, IDC_CALLER, m_Caller);
+ DDV_MaxChars(pDX, m_Caller, 11);
+ DDX_CBString(pDX, IDC_TTY, m_TTY);
+ DDV_MaxChars(pDX, m_TTY, 15);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CCalleeDlg, CDialog)
+ //{{AFX_MSG_MAP(CCalleeDlg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCalleeDlg message handlers
+
+BOOL CCalleeDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+POSITION p = app->m_t42Callees.GetHeadPosition();
+ m_CalleeCtl.ResetContent();
+ while(p){
+ CString callee = app->m_t42Callees.GetNext(p);
+ m_CalleeCtl.AddString(callee);
+ if(m_Callee.IsEmpty())
+ m_Callee = callee;
+ }
+ m_CallerCtl.ResetContent();
+ p = app->m_t42Callers.GetHeadPosition();
+ while(p){
+ CString caller = app->m_t42Callers.GetNext(p);
+ m_CallerCtl.AddString(caller);
+ if(m_Caller.IsEmpty())
+ m_Caller = caller;
+ }
+ UpdateData(FALSE);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CCalleeDlg::OnOK()
+{
+ UpdateData(TRUE);
+ if(m_Caller.IsEmpty())
+ VERIFY(m_Caller.LoadString(IDS_DEFAULTCALLER));
+CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ app->LastCaller(m_Caller);
+ CDialog::OnOK();
+}
diff --git a/CalleeDlg.h b/CalleeDlg.h
new file mode 100644
index 0000000..0044ba1
--- a/dev/null
+++ b/CalleeDlg.h
@@ -0,0 +1,40 @@
+// CalleeDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CCalleeDlg dialog
+
+class CCalleeDlg : public CDialog
+{
+// Construction
+public:
+ CCalleeDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CCalleeDlg)
+ enum { IDD = IDD_REMOTE };
+ CComboBox m_CallerCtl;
+ CComboBox m_CalleeCtl;
+ CString m_Callee;
+ CString m_Caller;
+ CString m_TTY;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCalleeDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CCalleeDlg)
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/ColorButton.cpp b/ColorButton.cpp
new file mode 100644
index 0000000..d702875
--- a/dev/null
+++ b/ColorButton.cpp
@@ -0,0 +1,92 @@
+// ColorButton.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "ColorButton.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CColorButton
+
+CColorButton::CColorButton()
+{
+}
+
+CColorButton::~CColorButton()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CColorButton, CButton)
+ //{{AFX_MSG_MAP(CColorButton)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CColorButton message handlers
+
+
+void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
+{
+ ASSERT(lpDrawItemStruct->CtlType==ODT_BUTTON);
+CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
+CRect rc(lpDrawItemStruct->rcItem);
+ pDC->DrawFrameControl(
+ &rc,
+ DFC_BUTTON,
+ DFCS_BUTTONPUSH|(
+ (lpDrawItemStruct->itemState&ODS_DISABLED)
+ ? DFCS_INACTIVE
+ : (
+ (lpDrawItemStruct->itemState&ODS_SELECTED)
+ ? DFCS_PUSHED
+ : 0
+ )
+ )|DFCS_ADJUSTRECT
+ );
+ if(!(lpDrawItemStruct->itemState&ODS_DISABLED)){
+ CBrush b(m_Color);
+ pDC->FillRect(rc,&b);
+ if(lpDrawItemStruct->itemState&ODS_FOCUS)
+ pDC->DrawFocusRect(rc);
+ }
+CString txt;
+ GetWindowText(txt);
+ if((lpDrawItemStruct->itemState&ODS_DISABLED)){
+ CSize sz = pDC->GetOutputTextExtent(txt);
+ if(txt.Find('&')>=0)
+ sz.cx-=pDC->GetOutputTextExtent("&",1).cx;
+ CRect rcc;
+ rcc.top=rcc.bottom=rc.CenterPoint().y;
+ rcc.left=rcc.right=rc.CenterPoint().x;
+ rcc.InflateRect(sz.cx/2,sz.cy/2);
+ pDC->DrawState(rcc.TopLeft(),rcc.Size(),(LPCTSTR)txt,DST_PREFIXTEXT|DSS_DISABLED,TRUE,0,(HBRUSH)NULL);
+ }else{
+ COLORREF ocol = pDC->SetTextColor(/*RGB(255,255,255)^*/~m_Color);
+ int omo = pDC->SetBkMode(TRANSPARENT);
+ pDC->DrawText(txt,&rc,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
+ pDC->SetBkMode(omo);
+ pDC->SetTextColor(ocol);
+ }
+}
+
+COLORREF CColorButton::SelectColor(COLORREF color)
+{
+CColorDialog cd(color,CC_RGBINIT,this);
+ if(cd.DoModal()==IDOK)
+ return cd.GetColor();
+ else
+ return color;
+}
+
+void CColorButton::SetColor()
+{
+ m_Color=SelectColor(m_Color);
+ Invalidate();
+}
diff --git a/ColorButton.h b/ColorButton.h
new file mode 100644
index 0000000..98e2f62
--- a/dev/null
+++ b/ColorButton.h
@@ -0,0 +1,47 @@
+#ifndef __COLORBUTTON_H
+#define __COLORBUTTON_H
+
+// ColorButton.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CColorButton window
+
+class CColorButton : public CButton
+{
+// Construction
+public:
+ void SetColor();
+ COLORREF SelectColor(COLORREF color);
+ CBrush m_brColor;
+ COLORREF m_Color;
+ CColorButton();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CColorButton)
+ public:
+ virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CColorButton();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CColorButton)
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __COLORBUTTON_H
diff --git a/FontsPage.cpp b/FontsPage.cpp
new file mode 100644
index 0000000..772f962
--- a/dev/null
+++ b/FontsPage.cpp
@@ -0,0 +1,333 @@
+// FontsPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "FontsPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CFontsPage property page
+
+IMPLEMENT_DYNCREATE(CFontsPage, CPropertyPage)
+
+CFontsPage::CFontsPage() : CPropertyPage(CFontsPage::IDD)
+{
+ //{{AFX_DATA_INIT(CFontsPage)
+ //}}AFX_DATA_INIT
+CRichEditCtrl tmp;
+ tmp.Create(WS_CHILD,CRect(0,0,0,0),AfxGetApp()->m_pMainWnd,0);
+ memset(&m_fmtChar,0,sizeof(m_fmtChar));
+ m_fmtLast=NULL;
+}
+
+CFontsPage::~CFontsPage()
+{
+}
+
+void CFontsPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CFontsPage)
+ DDX_Control(pDX, IDC_TIP, m_TipCtl);
+ DDX_Control(pDX, IDC_FORECOLOR, m_fgColorCtl);
+ DDX_Control(pDX, IDC_BACKCOLOR, m_bgColorCtl);
+ DDX_Control(pDX, IDC_CHARSET, m_CharsetCtl);
+ DDX_Control(pDX, IDC_UNDERLINE, m_UnderlineCtl);
+ DDX_Control(pDX, IDC_STRIKEOUT, m_StrikeoutCtl);
+ DDX_Control(pDX, IDC_ITALIC, m_ItalicCtl);
+ DDX_Control(pDX, IDC_BOLD, m_BoldCtl);
+ DDX_Control(pDX, IDC_FONTSIZE, m_SizeCtl);
+ DDX_Control(pDX, IDC_FORMATNAME, m_FormatsCtl);
+ DDX_Control(pDX, IDC_FACES, m_FacesCtl);
+ DDX_Control(pDX, IDC_SAMPLE, m_SampleCtl);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CFontsPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CFontsPage)
+ ON_CBN_SELENDOK(IDC_FACES, OnSelendokFaces)
+ ON_BN_CLICKED(IDC_BOLD, OnBold)
+ ON_CBN_SELENDOK(IDC_FONTSIZE, OnSelendokFontsize)
+ ON_CBN_EDITCHANGE(IDC_FONTSIZE, OnEditchangeFontsize)
+ ON_BN_CLICKED(IDC_ITALIC, OnItalic)
+ ON_BN_CLICKED(IDC_STRIKEOUT, OnStrikeout)
+ ON_BN_CLICKED(IDC_UNDERLINE, OnUnderline)
+ ON_CBN_SELENDOK(IDC_CHARSET, OnSelendokCharset)
+ ON_BN_CLICKED(IDC_BACKCOLOR, OnBackcolor)
+ ON_BN_CLICKED(IDC_FORECOLOR, OnForecolor)
+ ON_LBN_SELCHANGE(IDC_FORMATNAME, OnSelchangeFormatname)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFontsPage message handlers
+
+BOOL CFontsPage::OnInitDialog()
+{
+ CPropertyPage::OnInitDialog();
+
+ m_SampleCtl.GetDefaultCharFormat(m_fmtDefChar);
+
+ // Fill in faces combo
+ m_FacesCtl.ResetContent();
+CClientDC dc(NULL);
+LOGFONT lf;
+ memset(&lf,0,sizeof(lf));
+ lf.lfCharSet = DEFAULT_CHARSET;
+ EnumFontFamiliesEx(dc.m_hDC,&lf,(FONTENUMPROC)FillInFaces,(LPARAM)&m_FacesCtl,0);
+
+ // Fill in formats list
+ FillInFormats();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+int CALLBACK CFontsPage::FillInFaces(const ENUMLOGFONTEX* lpelfe,const TEXTMETRIC* lpntme,const int FontType,const LPARAM lParam)
+{
+// if(FontType!=TRUETYPE_FONTTYPE)
+// return 1;
+CComboBox* cb = (CComboBox*)lParam;
+ ASSERT(cb);
+ if(cb->FindString(0,lpelfe->elfLogFont.lfFaceName)>=0)
+ return 1;
+ cb->AddString(lpelfe->elfLogFont.lfFaceName);
+ return 1;
+}
+
+
+void CFontsPage::UpdateFormat(BOOL bSave)
+{
+ if(bSave){
+ CString tmp;
+ m_FacesCtl.GetWindowText(tmp);
+ strcpy(m_fmtChar.szFaceName,tmp); m_fmtChar.dwMask|=CFM_FACE;
+ m_SizeCtl.GetWindowText(tmp);
+ m_fmtChar.yHeight = atoi(tmp)?(atoi(tmp)*REFS2PTS):m_fmtChar.yHeight;
+ m_fmtChar.dwMask|=CFM_SIZE;
+ if(m_BoldCtl.GetCheck())
+ m_fmtChar.dwEffects|=CFE_BOLD;
+ else
+ m_fmtChar.dwEffects&=~CFE_BOLD;
+ m_fmtChar.dwMask|=CFM_BOLD;
+ if(m_ItalicCtl.GetCheck())
+ m_fmtChar.dwEffects|=CFE_ITALIC;
+ else
+ m_fmtChar.dwEffects&=~CFE_ITALIC;
+ m_fmtChar.dwMask|=CFM_ITALIC;
+ if(m_StrikeoutCtl.GetCheck())
+ m_fmtChar.dwEffects|=CFE_STRIKEOUT;
+ else
+ m_fmtChar.dwEffects&=~CFE_STRIKEOUT;
+ m_fmtChar.dwMask|=CFM_STRIKEOUT;
+ if(m_UnderlineCtl.GetCheck())
+ m_fmtChar.dwEffects|=CFE_UNDERLINE;
+ else
+ m_fmtChar.dwEffects&=~CFE_UNDERLINE;
+ m_fmtChar.dwMask|=CFM_UNDERLINE;
+ if(m_CharsetCtl.IsWindowEnabled())
+ m_fmtChar.bCharSet=m_CharsetCtl.GetItemData(m_CharsetCtl.GetCurSel());
+ else
+ m_fmtChar.bCharSet=DEFAULT_CHARSET;
+ m_fmtChar.crTextColor = m_fgColorCtl.m_Color;
+ m_fmtChar.dwMask|=CFM_COLOR;
+ m_fmtChar.dwEffects&=~CFE_AUTOCOLOR;
+ UpdateSample();
+ }else{
+ if(m_fmtChar.cbSize!=sizeof(m_fmtChar))
+ memmove(&m_fmtChar,&m_fmtDefChar,sizeof(m_fmtChar));
+ if(m_fmtChar.dwMask&CFM_FACE)
+ m_FacesCtl.SelectString(0,m_fmtChar.szFaceName);
+ CString tmp;
+ if(m_fmtChar.dwMask&CFM_SIZE){
+ tmp.Format("%d",m_fmtChar.yHeight/REFS2PTS);
+ m_SizeCtl.SetWindowText(tmp);
+ }
+ if(m_fmtChar.dwMask&CFM_BOLD)
+ m_BoldCtl.SetCheck((m_fmtChar.dwEffects&CFE_BOLD)?1:0);
+ if(m_fmtChar.dwMask&CFM_ITALIC)
+ m_ItalicCtl.SetCheck((m_fmtChar.dwEffects&CFE_ITALIC)?1:0);
+ if(m_fmtChar.dwMask&CFM_STRIKEOUT)
+ m_StrikeoutCtl.SetCheck((m_fmtChar.dwEffects&CFE_STRIKEOUT)?1:0);
+ if(m_fmtChar.dwMask&CFM_UNDERLINE)
+ m_UnderlineCtl.SetCheck((m_fmtChar.dwEffects&CFE_UNDERLINE)?1:0);
+ m_fgColorCtl.m_Color = (m_fmtChar.dwMask&CFM_COLOR)?m_fmtChar.crTextColor:0;
+ m_fgColorCtl.Invalidate();
+ FillCharsets();
+ }
+}
+
+void CFontsPage::UpdateSample()
+{
+ m_SampleCtl.SetReadOnly(TRUE);
+ m_SampleCtl.SetTargetDevice(NULL,0);
+ m_SampleCtl.SetSel(0,-1);
+ m_SampleCtl.ReplaceSel(
+ (m_fmtChar.dwMask&CFM_FACE)
+ ? (
+ (*m_fmtChar.szFaceName)
+ ? m_fmtChar.szFaceName
+ : "Sample"
+ )
+ : "Sample"
+ );
+ m_SampleCtl.SetSel(0,-1);
+ m_SampleCtl.SetSelectionCharFormat(m_fmtChar);
+PARAFORMAT pf;
+ memset(&pf,0,sizeof(pf));
+ pf.cbSize = sizeof(pf);
+ pf.dwMask = PFM_ALIGNMENT;
+ pf.wAlignment = PFA_CENTER;
+ m_SampleCtl.SetParaFormat(pf);
+ m_SampleCtl.HideSelection(TRUE,TRUE);
+ if(m_bgColorCtl.IsWindowEnabled())
+ m_SampleCtl.SetBackgroundColor(FALSE,m_bgColorCtl.m_Color);
+}
+
+void CFontsPage::OnSelendokFaces()
+{
+ UpdateFormat(TRUE);
+ FillCharsets();
+}
+
+void CFontsPage::OnSelendokFontsize()
+{
+CString tmp;
+ m_SizeCtl.GetLBText(m_SizeCtl.GetCurSel(),tmp);
+ m_SizeCtl.SetWindowText(tmp);
+ UpdateFormat(TRUE);
+}
+void CFontsPage::OnEditchangeFontsize()
+{
+ UpdateFormat(TRUE);
+}
+
+void CFontsPage::OnBold()
+{
+ UpdateFormat(TRUE);
+}
+void CFontsPage::OnItalic()
+{
+ UpdateFormat(TRUE);
+}
+void CFontsPage::OnStrikeout()
+{
+ UpdateFormat(TRUE);
+}
+void CFontsPage::OnUnderline()
+{
+ UpdateFormat(TRUE);
+}
+
+void CFontsPage::FillCharsets()
+{
+ m_CharsetCtl.EnableWindow(TRUE);
+ m_CharsetCtl.ResetContent();
+CString tmp;
+ tmp.LoadString(IDS_CHARSET_AUTO);
+ VERIFY(m_CharsetCtl.AddString(tmp)==0);
+ VERIFY(m_CharsetCtl.SetItemData(0,DEFAULT_CHARSET)!=LB_ERR);
+ if(m_fmtChar.dwMask&CFM_FACE && *m_fmtChar.szFaceName){
+ CClientDC dc(NULL);
+ LOGFONT lf;
+ memset(&lf,0,sizeof(lf));
+ lf.lfCharSet = DEFAULT_CHARSET;
+ strcpy(lf.lfFaceName,m_fmtChar.szFaceName);
+ EnumFontFamiliesEx(dc.m_hDC,&lf,(FONTENUMPROC)FillInCharsets,(LPARAM)&m_CharsetCtl,0);
+ }
+int ii = m_CharsetCtl.GetCount();
+ for(int i=0;i<ii;i++){
+ if(m_CharsetCtl.GetItemData(i)==m_fmtChar.bCharSet){
+ m_CharsetCtl.SetCurSel(i);
+ break;
+ }
+ }
+ m_CharsetCtl.EnableWindow(m_CharsetCtl.GetCount()>1);
+}
+
+int CALLBACK CFontsPage::FillInCharsets(const ENUMLOGFONTEX* lpelfe,const TEXTMETRIC* lpntme,const int FontType,const LPARAM lParam)
+{
+// if(FontType!=TRUETYPE_FONTTYPE)
+// return 1;
+CComboBox* cb = (CComboBox*)lParam;
+ ASSERT(cb);
+ if(cb->FindString(0,(char*)lpelfe->elfScript)>=0)
+ return 1;
+int i = cb->AddString((char*)lpelfe->elfScript);
+ ASSERT(i>=0);
+ VERIFY(cb->SetItemData(i,lpelfe->elfLogFont.lfCharSet)!=LB_ERR);
+ return 1;
+}
+
+void CFontsPage::OnSelendokCharset()
+{
+ UpdateFormat(TRUE);
+}
+
+void CFontsPage::FillInFormats()
+{
+ AddFmt(IDS_FMT_T42LOCAL,&m_fmtT42Local);
+ AddFmt(IDS_FMT_T42REMOTE,&m_fmtT42Remote);
+ AddFmt(IDS_FMT_T42SYSTEM,&m_fmtT42System,0);
+ m_FormatsCtl.SetCurSel(0);
+ OnSelchangeFormatname();
+}
+void CFontsPage::AddFmt(UINT name,CFontFormat* cf,UINT flags)
+{
+CString f;
+ VERIFY(f.LoadString(name));
+int lf = f.Find('\n');
+int i = m_FormatsCtl.AddString((lf<0)?f:f.Left(lf));
+ ASSERT(i>=0);
+ m_FormatsCtl.SetItemData(i,(LPARAM)cf);
+ cf->m_Tip = (lf<0)?"":f.Mid(lf+1);
+ cf->m_Flags = flags;
+}
+void CFontsPage::OnSelchangeFormatname()
+{
+CFontFormat* fmt = (CFontFormat*)m_FormatsCtl.GetItemData(m_FormatsCtl.GetCurSel());
+ if(m_fmtLast){
+ memmove(&m_fmtLast->m_fmtChar,&m_fmtChar,sizeof(m_fmtLast->m_fmtChar));
+ if(m_fmtLast->m_Flags&CFontFormat::flagBGColor)
+ m_fmtLast->m_bgColor = m_bgColorCtl.m_Color;
+ }
+BOOL bBG = fmt->m_Flags&CFontFormat::flagBGColor;
+ m_bgColorCtl.EnableWindow(bBG);
+ m_TipCtl.SetWindowText(fmt->m_Tip);
+ m_fmtLast = fmt;
+ memmove(&m_fmtChar,&m_fmtLast->m_fmtChar,sizeof(m_fmtChar));
+ if(bBG){
+ m_bgColorCtl.m_Color = m_fmtLast->m_bgColor;
+ m_bgColorCtl.Invalidate();
+ }
+ UpdateFormat(FALSE);
+ UpdateSample();
+}
+
+void CFontsPage::OnBackcolor()
+{
+ m_bgColorCtl.SetColor();
+ UpdateFormat(TRUE);
+}
+void CFontsPage::OnForecolor()
+{
+ m_fgColorCtl.SetColor();
+ UpdateFormat(TRUE);
+}
+
+void CFontsPage::OnOK()
+{
+ if(m_fmtLast){
+ memmove(&m_fmtLast->m_fmtChar,&m_fmtChar,sizeof(m_fmtLast->m_fmtChar));
+ if(m_fmtLast->m_Flags&CFontFormat::flagBGColor)
+ m_fmtLast->m_bgColor = m_bgColorCtl.m_Color;
+ }
+ CPropertyPage::OnOK();
+}
diff --git a/FontsPage.h b/FontsPage.h
new file mode 100644
index 0000000..96c2b97
--- a/dev/null
+++ b/FontsPage.h
@@ -0,0 +1,87 @@
+// FontsPage.h : header file
+//
+
+#include "ColorButton.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CFontsPage dialog
+
+struct CFontFormat {
+ CHARFORMAT m_fmtChar;
+ COLORREF m_bgColor;
+ enum _flags {
+ flagBGColor = 1
+ };
+ int m_Flags;
+ CString m_Tip;
+};
+
+class CFontsPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CFontsPage)
+
+// Construction
+public:
+ CHARFORMAT m_fmtDefChar;
+ CFontFormat* m_fmtLast;
+ void AddFmt(UINT name,CFontFormat* cf,UINT flags=CFontFormat::flagBGColor);
+ void FillInFormats();
+ CFontFormat m_fmtT42System;
+ CFontFormat m_fmtT42Remote;
+ CFontFormat m_fmtT42Local;
+ static int CALLBACK FillInCharsets(const ENUMLOGFONTEX* lpelfe,const TEXTMETRIC* lpntme,const int FontType,const LPARAM lParam);
+ void FillCharsets();
+ void UpdateSample();
+ void UpdateFormat(BOOL bSave=FALSE);
+ CHARFORMAT m_fmtChar;
+ static int CALLBACK FillInFaces(const ENUMLOGFONTEX* lpelfe,const TEXTMETRIC* lpntme,const int FontType,const LPARAM lParam);
+ CFontsPage();
+ ~CFontsPage();
+
+// Dialog Data
+ //{{AFX_DATA(CFontsPage)
+ enum { IDD = IDD_OPTIONS_FONTS };
+ CStatic m_TipCtl;
+ CColorButton m_fgColorCtl;
+ CColorButton m_bgColorCtl;
+ CComboBox m_CharsetCtl;
+ CButton m_UnderlineCtl;
+ CButton m_StrikeoutCtl;
+ CButton m_ItalicCtl;
+ CButton m_BoldCtl;
+ CComboBox m_SizeCtl;
+ CListBox m_FormatsCtl;
+ CComboBox m_FacesCtl;
+ CRichEditCtrl m_SampleCtl;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CFontsPage)
+ public:
+ virtual void OnOK();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CFontsPage)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnSelendokFaces();
+ afx_msg void OnBold();
+ afx_msg void OnSelendokFontsize();
+ afx_msg void OnEditchangeFontsize();
+ afx_msg void OnItalic();
+ afx_msg void OnStrikeout();
+ afx_msg void OnUnderline();
+ afx_msg void OnSelendokCharset();
+ afx_msg void OnBackcolor();
+ afx_msg void OnForecolor();
+ afx_msg void OnSelchangeFormatname();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
diff --git a/GeneralPage.cpp b/GeneralPage.cpp
new file mode 100644
index 0000000..78863fc
--- a/dev/null
+++ b/GeneralPage.cpp
@@ -0,0 +1,100 @@
+// GeneralPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "GeneralPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CGeneralPage property page
+
+IMPLEMENT_DYNCREATE(CGeneralPage, CPropertyPage)
+
+CGeneralPage::CGeneralPage() : CPropertyPage(CGeneralPage::IDD)
+{
+ //{{AFX_DATA_INIT(CGeneralPage)
+ //}}AFX_DATA_INIT
+ m_ntalkPort = 518;
+}
+
+CGeneralPage::~CGeneralPage()
+{
+}
+
+void CGeneralPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CGeneralPage)
+ DDX_Control(pDX, IDC_NTALKPORTSPIN, m_ntalkSpinCtl);
+ DDX_Control(pDX, IDC_NTALKPORT, m_ntalkPortCtl);
+ //}}AFX_DATA_MAP
+ if(pDX->m_bSaveAndValidate){
+ pDX->PrepareEditCtrl(IDC_NTALKPORT);
+ CString ntp;
+ m_ntalkPortCtl.GetWindowText(ntp);
+ UINT p = atoi(ntp);
+ if(!p){
+ servent* se = getservbyname((LPCTSTR)ntp,"udp");
+ if(se)
+ p = ntohs(se->s_port);
+ else{
+ AfxMessageBox(IDS_FAILVALIDATE_NTALKPORT,MB_OK|MB_ICONSTOP);
+ pDX->Fail();
+ return;
+ }
+ }
+ m_ntalkPort = p;
+ }
+}
+
+
+BEGIN_MESSAGE_MAP(CGeneralPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CGeneralPage)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_NTALKPORTSPIN, OnDeltaposNtalkportspin)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CGeneralPage message handlers
+
+BOOL CGeneralPage::OnInitDialog()
+{
+ CPropertyPage::OnInitDialog();
+
+ m_ntalkSpinCtl.SetRange(1,min(UD_MAXVAL,65535));
+ m_ntalkSpinCtl.SetPos(m_ntalkPort);
+ SetPortCtl();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CGeneralPage::SetPortCtl()
+{
+servent* se = getservbyport(htons(m_ntalkPort),"udp");
+ if(se)
+ m_ntalkPortCtl.SetWindowText(se->s_name);
+ else{
+ CString tmp;
+ tmp.Format("%u",m_ntalkPort);
+ m_ntalkPortCtl.SetWindowText(tmp);
+ }
+}
+
+void CGeneralPage::OnDeltaposNtalkportspin(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+
+ TRACE3("UD iP %d, iD %d, p %d\n",pNMUpDown->iPos,
+ pNMUpDown->iDelta, m_ntalkSpinCtl.GetPos());
+ m_ntalkPort = pNMUpDown->iPos+pNMUpDown->iDelta;
+ SetPortCtl();
+
+ *pResult = 0;
+}
diff --git a/GeneralPage.h b/GeneralPage.h
new file mode 100644
index 0000000..134e747
--- a/dev/null
+++ b/GeneralPage.h
@@ -0,0 +1,42 @@
+// GeneralPage.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CGeneralPage dialog
+
+class CGeneralPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CGeneralPage)
+
+// Construction
+public:
+ void SetPortCtl();
+ UINT m_ntalkPort;
+ CGeneralPage();
+ ~CGeneralPage();
+
+// Dialog Data
+ //{{AFX_DATA(CGeneralPage)
+ enum { IDD = IDD_OPTIONS_GENERAL };
+ CSpinButtonCtrl m_ntalkSpinCtl;
+ CEdit m_ntalkPortCtl;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CGeneralPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CGeneralPage)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDeltaposNtalkportspin(NMHDR* pNMHDR, LRESULT* pResult);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
diff --git a/KTAGS b/KTAGS
new file mode 100644
index 0000000..53a4c56
--- a/dev/null
+++ b/KTAGS
@@ -0,0 +1,12 @@
+about-date T42.rc /LTEXT\s\+"Copyright /;" kind:d
+about-version T42.rc /LTEXT\s\+"T42, Version/;" kind:v
+help-license-date ./help/T42.xml /<license\s/;" kind:d
+help-news ./help/T42.xml /<newsfor\s/
+install-version ./install/install.cpp /^#define\s\+KINAME\s\+"/;" kind:v
+install-vsinfo-date install/install.rc /^\s\+VALUE\s\+"LegalCopyright",/;" kind:d
+install-vsinfo-numeric-version install/install.rc /^\s\+FILEVERSION\s\+/;" kind:v
+install-vsinfo-string-version install/install.rc /^\s\+VALUE\s\+"FileVersion",/;" kind:v
+license-date COPYING :1;" kind:d
+vsinfo-date T42.rc /VALUE\s\+"LegalCopyright",/;" kind:d
+vsinfo-numeric-version T42.rc /^\s\+FILEVERSION\s\+/;" kind:v
+vsinfo-string-version T42.rc /^\s\+VALUE\s\+"FileVersion",/;" kind:v
diff --git a/README b/README
new file mode 100644
index 0000000..fbdfd9c
--- a/dev/null
+++ b/README
@@ -0,0 +1,33 @@
+
+Before compiling canned install executable the following files should be placed
+in the build tree:
+
+redist/mfc42.dl_
+
+Release checklist:
+ (These are tags stored in KTAGS file. please, keep in sync. Use vim to
+ jump to these tags. I haven't tried it on windows, though).
+
+|help-news| - Release notes in help file
+
+Version number in the following places:
+
+|about-version| - About box
+|vsinfo-numeric-version| - VERSIONINFO numerical File&Prod V
+|vsinfo-string-version| - VERSIONINFO string File&Prod V
+|install-version| - Version used in install
+|install-vsinfo-numeric-version| - install's VERSIONINFO block
+|install-vsinfo-string-version| - install's VERSIONINFO block
+
+If the year flips check these:
+
+|about-date| - About box
+|help-license-date| - license in help file
+|license-date| - license in COPYING file
+|vsinfo-date| - Copyright in VERSIONINFO block
+|install-vsinfo-date| - Copyright in install's VERSIONINFO
+ block
+
+
+This is for vim (don't remove):
+ vim:set tags=KTAGS isk=!-~,^*,^\|,^\" ft=help:
diff --git a/SecretaryPage.cpp b/SecretaryPage.cpp
new file mode 100644
index 0000000..affac08
--- a/dev/null
+++ b/SecretaryPage.cpp
@@ -0,0 +1,116 @@
+// SecretaryPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "SecretaryPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CSecretaryPage property page
+
+IMPLEMENT_DYNCREATE(CSecretaryPage, CPropertyPage)
+
+CSecretaryPage::CSecretaryPage() : CPropertyPage(CSecretaryPage::IDD)
+{
+ //{{AFX_DATA_INIT(CSecretaryPage)
+ m_limitBytes = 0;
+ m_bLimitBytes = FALSE;
+ m_bLimitTime = FALSE;
+ m_Greeting = _T("");
+ m_limitTime = 0;
+ m_bLimitWin = FALSE;
+ m_limitWin = 0;
+ //}}AFX_DATA_INIT
+}
+
+CSecretaryPage::~CSecretaryPage()
+{
+}
+
+void CSecretaryPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSecretaryPage)
+ DDX_Control(pDX, IDC_DOWINLIMIT, m_bLimitWinCtl);
+ DDX_Control(pDX, IDC_WINSPIN, m_WinSpinCtl);
+ DDX_Control(pDX, IDC_TIMESPIN, m_TimeSpinCtl);
+ DDX_Control(pDX, IDC_WINLIMIT, m_limitWinCtl);
+ DDX_Control(pDX, IDC_CHARSPIN, m_CharSpinCtl);
+ DDX_Control(pDX, IDC_TIMELIMIT, m_limitTimeCtl);
+ DDX_Control(pDX, IDC_DOTIMELIMIT, m_bLimitTimeCtl);
+ DDX_Control(pDX, IDC_DOBYTELIMIT, m_bLimitBytesCtl);
+ DDX_Control(pDX, IDC_BYTELIMIT, m_limitBytesCtl);
+ DDX_Text(pDX, IDC_BYTELIMIT, m_limitBytes);
+ DDX_Check(pDX, IDC_DOBYTELIMIT, m_bLimitBytes);
+ DDX_Check(pDX, IDC_DOTIMELIMIT, m_bLimitTime);
+ DDX_Text(pDX, IDC_GREETING, m_Greeting);
+ DDX_Text(pDX, IDC_TIMELIMIT, m_limitTime);
+ DDX_Check(pDX, IDC_DOWINLIMIT, m_bLimitWin);
+ DDX_Text(pDX, IDC_WINLIMIT, m_limitWin);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CSecretaryPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CSecretaryPage)
+ ON_BN_CLICKED(IDC_DOBYTELIMIT, OnDobytelimit)
+ ON_BN_CLICKED(IDC_DOTIMELIMIT, OnDotimelimit)
+ ON_BN_CLICKED(IDC_DOWINLIMIT, OnDowinlimit)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSecretaryPage message handlers
+
+BOOL CSecretaryPage::OnInitDialog()
+{
+ CPropertyPage::OnInitDialog();
+
+ SetTimeLimit();
+ SetBytesLimit();
+ SetWinLimit();
+ m_TimeSpinCtl.SetRange(0,60);
+ m_WinSpinCtl.SetRange(0,100);
+ m_CharSpinCtl.SetRange(0,UD_MAXVAL);
+UDACCEL uda = {0,512};
+ m_CharSpinCtl.SetAccel(1,&uda);
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CSecretaryPage::SetTimeLimit()
+{
+ m_limitTimeCtl.EnableWindow(m_bLimitTimeCtl.GetCheck());
+}
+
+void CSecretaryPage::SetBytesLimit()
+{
+ m_limitBytesCtl.EnableWindow(m_bLimitBytesCtl.GetCheck());
+}
+
+void CSecretaryPage::SetWinLimit()
+{
+ m_limitWinCtl.EnableWindow(m_bLimitWinCtl.GetCheck());
+}
+
+void CSecretaryPage::OnDobytelimit()
+{
+ SetBytesLimit();
+}
+
+void CSecretaryPage::OnDotimelimit()
+{
+ SetTimeLimit();
+}
+
+void CSecretaryPage::OnDowinlimit()
+{
+ SetWinLimit();
+}
+
diff --git a/SecretaryPage.h b/SecretaryPage.h
new file mode 100644
index 0000000..108d933
--- a/dev/null
+++ b/SecretaryPage.h
@@ -0,0 +1,59 @@
+// SecretaryPage.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CSecretaryPage dialog
+
+class CSecretaryPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CSecretaryPage)
+
+// Construction
+public:
+ void SetWinLimit();
+ void SetBytesLimit();
+ void SetTimeLimit();
+ CSecretaryPage();
+ ~CSecretaryPage();
+
+// Dialog Data
+ //{{AFX_DATA(CSecretaryPage)
+ enum { IDD = IDD_OPTIONS_SECRETARY };
+ CButton m_bLimitWinCtl;
+ CSpinButtonCtrl m_WinSpinCtl;
+ CSpinButtonCtrl m_TimeSpinCtl;
+ CEdit m_limitWinCtl;
+ CSpinButtonCtrl m_CharSpinCtl;
+ CEdit m_limitTimeCtl;
+ CButton m_bLimitTimeCtl;
+ CButton m_bLimitBytesCtl;
+ CEdit m_limitBytesCtl;
+ UINT m_limitBytes;
+ BOOL m_bLimitBytes;
+ BOOL m_bLimitTime;
+ CString m_Greeting;
+ UINT m_limitTime;
+ BOOL m_bLimitWin;
+ UINT m_limitWin;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CSecretaryPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CSecretaryPage)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDobytelimit();
+ afx_msg void OnDotimelimit();
+ afx_msg void OnDowinlimit();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
diff --git a/SoundsPage.cpp b/SoundsPage.cpp
new file mode 100644
index 0000000..ba81736
--- a/dev/null
+++ b/SoundsPage.cpp
@@ -0,0 +1,148 @@
+// SoundsPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "SoundsPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CSoundsPage property page
+
+IMPLEMENT_DYNCREATE(CSoundsPage, CPropertyPage)
+
+CSoundsPage::CSoundsPage() : CPropertyPage(CSoundsPage::IDD)
+{
+ //{{AFX_DATA_INIT(CSoundsPage)
+ m_T42Bell = _T("");
+ m_T42Prompt = _T("");
+ m_bT42PromptLoop = FALSE;
+ m_T42Wake = _T("");
+ //}}AFX_DATA_INIT
+}
+
+CSoundsPage::~CSoundsPage()
+{
+}
+
+void CSoundsPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSoundsPage)
+ DDX_Control(pDX, IDC_T42WAKE_PLAY, m_T42WakePlayCtl);
+ DDX_Control(pDX, IDC_T42PROMPT_PLAY, m_T42PromptPlayCtl);
+ DDX_Control(pDX, IDC_T42BELL_PLAY, m_T42BellPlayCtl);
+ DDX_Control(pDX, IDC_T42WAKE_BROWSE, m_T42WakeBrowseCtl);
+ DDX_Control(pDX, IDC_T42WAKE, m_T42WakeCtl);
+ DDX_Control(pDX, IDC_T42PROMPT_BROWSE, m_T42PromptBrowseCtl);
+ DDX_Control(pDX, IDC_T42PROMPT, m_T42PromptCtl);
+ DDX_Control(pDX, IDC_T42BELL_BROWSE, m_T42BellBrowseCtl);
+ DDX_Control(pDX, IDC_T42BELL, m_T42BellCtl);
+ DDX_CBString(pDX, IDC_T42BELL, m_T42Bell);
+ DDX_CBString(pDX, IDC_T42PROMPT, m_T42Prompt);
+ DDX_Check(pDX, IDC_T42PROMPT_LOOP, m_bT42PromptLoop);
+ DDX_CBString(pDX, IDC_T42WAKE, m_T42Wake);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CSoundsPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CSoundsPage)
+ ON_BN_CLICKED(IDC_T42BELL_BROWSE, OnT42bellBrowse)
+ ON_BN_CLICKED(IDC_T42PROMPT_BROWSE, OnT42promptBrowse)
+ ON_BN_CLICKED(IDC_T42WAKE_BROWSE, OnT42wakeBrowse)
+ ON_BN_CLICKED(IDC_T42BELL_PLAY, OnT42bellPlay)
+ ON_BN_CLICKED(IDC_T42PROMPT_PLAY, OnT42promptPlay)
+ ON_BN_CLICKED(IDC_T42WAKE_PLAY, OnT42wakePlay)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSoundsPage message handlers
+
+BOOL CSoundsPage::OnInitDialog()
+{
+ CPropertyPage::OnInitDialog();
+
+CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ m_T42BellCtl.ResetContent();
+ m_T42BellCtl.AddString(app->m_sndTeaDrop);
+ m_T42PromptCtl.ResetContent();
+ m_T42PromptCtl.AddString(app->m_sndBoilingTeapot);
+ m_T42WakeCtl.ResetContent();
+ m_T42WakeCtl.AddString(app->m_sndTeapotWhistle);
+
+HICON i = app->LoadIcon(IDI_BROWSE);
+ m_T42BellBrowseCtl.SetIcon(i);
+ m_T42PromptBrowseCtl.SetIcon(i);
+ m_T42WakeBrowseCtl.SetIcon(i);
+ i = app->LoadIcon(IDI_PREPLAY);
+ m_T42BellPlayCtl.SetIcon(i);
+ m_T42PromptPlayCtl.SetIcon(i);
+ m_T42WakePlayCtl.SetIcon(i);
+
+ UpdateData(FALSE);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CSoundsPage::OnT42bellBrowse()
+{
+ BrowseForSound(m_T42BellCtl);
+}
+
+void CSoundsPage::OnT42promptBrowse()
+{
+ BrowseForSound(m_T42PromptCtl);
+}
+
+void CSoundsPage::OnT42wakeBrowse()
+{
+ BrowseForSound(m_T42WakeCtl);
+}
+
+void CSoundsPage::BrowseForSound(CComboBox& ctl)
+{
+CString f;
+ ctl.GetWindowText(f);
+CString filter;
+ filter.LoadString(IDS_FILTER_WAV);
+CFileDialog fd(TRUE,NULL,(LPCTSTR)f,
+ OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY
+ |OFN_LONGNAMES|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST,
+ filter,this);
+CString title;
+ title.LoadString(IDS_TITLE_WAV);
+ fd.m_ofn.lpstrTitle=(LPCTSTR)title;
+ if(fd.DoModal()==IDOK)
+ ctl.SetWindowText(fd.GetPathName());
+}
+
+void CSoundsPage::OnT42bellPlay()
+{
+ PlayIt(m_T42BellCtl);
+}
+void CSoundsPage::OnT42promptPlay()
+{
+ PlayIt(m_T42PromptCtl);
+}
+void CSoundsPage::OnT42wakePlay()
+{
+ PlayIt(m_T42WakeCtl);
+}
+
+void CSoundsPage::PlayIt(CComboBox& ctl,BOOL bLoop)
+{
+CString s;
+ ctl.GetWindowText(s);
+CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ app->StartSound(s,bLoop);
+}
diff --git a/SoundsPage.h b/SoundsPage.h
new file mode 100644
index 0000000..ea67fc3
--- a/dev/null
+++ b/SoundsPage.h
@@ -0,0 +1,58 @@
+// SoundsPage.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CSoundsPage dialog
+
+class CSoundsPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CSoundsPage)
+
+// Construction
+public:
+ void PlayIt(CComboBox& ctl,BOOL bLoop=FALSE);
+ void BrowseForSound(CComboBox& ctl);
+ CSoundsPage();
+ ~CSoundsPage();
+
+// Dialog Data
+ //{{AFX_DATA(CSoundsPage)
+ enum { IDD = IDD_OPTIONS_SOUNDS };
+ CButton m_T42WakePlayCtl;
+ CButton m_T42PromptPlayCtl;
+ CButton m_T42BellPlayCtl;
+ CButton m_T42WakeBrowseCtl;
+ CComboBox m_T42WakeCtl;
+ CButton m_T42PromptBrowseCtl;
+ CComboBox m_T42PromptCtl;
+ CButton m_T42BellBrowseCtl;
+ CComboBox m_T42BellCtl;
+ CString m_T42Bell;
+ CString m_T42Prompt;
+ BOOL m_bT42PromptLoop;
+ CString m_T42Wake;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CSoundsPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CSoundsPage)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnT42bellBrowse();
+ afx_msg void OnT42promptBrowse();
+ afx_msg void OnT42wakeBrowse();
+ afx_msg void OnT42bellPlay();
+ afx_msg void OnT42promptPlay();
+ afx_msg void OnT42wakePlay();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
diff --git a/T42.clw b/T42.clw
new file mode 100644
index 0000000..120b3c9
--- a/dev/null
+++ b/T42.clw
@@ -0,0 +1,367 @@
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CT42Dlg
+LastTemplate=CPropertyPage
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "T42.h"
+
+ClassCount=16
+Class1=CT42App
+Class2=CT42Dlg
+Class3=CAboutDlg
+
+ResourceCount=11
+Resource1=IDD_OPTIONS_FONTS
+Resource2=IDM_POPUPS
+Resource3=IDD_OPTIONS_SOUNDS
+Class4=T42Frame
+Class5=CCalleeDlg
+Resource4=IDD_T42VIEW
+Resource5=IDD_OPTIONS_GENERAL
+Class6=T42View
+Class7=T42Document
+Class8=CSplitBar
+Class9=CLocalCtl
+Class10=CRemoteCtl
+Resource6=IDD_REMOTE
+Class11=T42AnnounceDlg
+Resource7=IDD_OPTIONS_SECRETARY
+Resource8=IDD_T42_DIALOG
+Class12=CSoundsPage
+Resource9=IDD_ANNOUNCE
+Class13=CFontsPage
+Class14=CColorButton
+Class15=CSecretaryPage
+Resource10=IDD_ABOUTBOX
+Class16=CGeneralPage
+Resource11=IDR_T42FRAME
+
+[CLS:CT42App]
+Type=0
+HeaderFile=T42.h
+ImplementationFile=T42.cpp
+Filter=N
+LastObject=CT42App
+
+[CLS:CT42Dlg]
+Type=0
+HeaderFile=T42Dlg.h
+ImplementationFile=T42Dlg.cpp
+Filter=W
+LastObject=CT42Dlg
+BaseClass=CDialog
+VirtualFilter=dWC
+
+[CLS:CAboutDlg]
+Type=0
+HeaderFile=T42Dlg.h
+ImplementationFile=T42Dlg.cpp
+Filter=D
+BaseClass=CDialog
+VirtualFilter=dWC
+LastObject=IDC_KLEVERNET
+
+[DLG:IDD_ABOUTBOX]
+Type=1
+Class=CAboutDlg
+ControlCount=6
+Control1=IDC_STATIC,static,1342308480
+Control2=IDC_STATIC,static,1342308352
+Control3=IDC_STATIC,static,1342177283
+Control4=IDC_STATIC,static,1342177283
+Control5=IDOK,button,1342373889
+Control6=IDC_KLEVERNET,button,1342242816
+
+[DLG:IDD_T42_DIALOG]
+Type=1
+Class=CT42Dlg
+ControlCount=12
+Control1=IDC_STATIC,static,1342308353
+Control2=IDC_ONCALL,combobox,1344339971
+Control3=IDC_STATIC,static,1342308353
+Control4=IDC_ONCALLAWAY,combobox,1344339971
+Control5=IDC_CALLS,SysListView32,1350631425
+Control6=IDC_PREVIEW,RICHEDIT,1344389508
+Control7=IDC_TALK,button,1342242816
+Control8=IDC_OPTIONS,button,1342242816
+Control9=IDOK,button,1342242816
+Control10=ID_HELP,button,1342242816
+Control11=IDCANCEL,button,1073807361
+Control12=IDC_AWAY,button,1342255107
+
+[CLS:T42Frame]
+Type=0
+HeaderFile=T42Frame.h
+ImplementationFile=T42Frame.cpp
+BaseClass=CFrameWnd
+Filter=W
+LastObject=ID_CALLLOG_CALLBACK
+VirtualFilter=fWC
+
+[MNU:IDR_T42FRAME]
+Type=1
+Class=?
+Command1=ID_TALK_REMOTEUSER
+Command2=ID_TALK_ABORT
+Command3=ID_TALK_RECONNECT
+Command4=ID_TEA_SAVE
+Command5=ID_TALK_CLOSE
+Command6=ID_EDIT_COPY
+Command7=ID_EDIT_PASTE
+Command8=ID_SLEEP_SLEEP
+Command9=ID_SLEEP_SLEEPONMINIMIZE
+Command10=ID_SLEEP_MINIMIZEONSLEEP
+Command11=ID_SLEEP_WAKEUPACTION_MAKESOUND
+Command12=ID_SLEEP_WAKEUPACTION_POPUP
+Command13=ID_WINDOW_SPLITEQUALLY
+Command14=ID_WINDOW_SAVELAYOUT
+Command15=ID_WINDOW_AUTOSAVELAYOUT
+Command16=ID_WINDOW_HORIZONTALSPLIT
+Command17=ID_WINDOW_VERTICALSPLIT
+Command18=ID_WINDOW_HIDEINTRAYONMINIMIZE
+CommandCount=18
+
+[DLG:IDD_REMOTE]
+Type=1
+Class=CCalleeDlg
+ControlCount=9
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_CALLEE,combobox,1344340034
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_TTY,combobox,1344340034
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_CALLER,combobox,1344340034
+Control8=IDOK,button,1342242817
+Control9=IDCANCEL,button,1342242816
+
+[CLS:CCalleeDlg]
+Type=0
+HeaderFile=CalleeDlg.h
+ImplementationFile=CalleeDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CCalleeDlg
+VirtualFilter=dWC
+
+[DLG:IDD_T42VIEW]
+Type=1
+Class=T42View
+ControlCount=1
+Control1=IDC_SPLIT,static,1342177547
+
+[CLS:T42View]
+Type=0
+HeaderFile=T42View.h
+ImplementationFile=T42View.cpp
+BaseClass=CFormView
+Filter=W
+LastObject=ID_CALLLOG_CALLBACK
+VirtualFilter=VWC
+
+[CLS:T42Document]
+Type=0
+HeaderFile=T42Document.h
+ImplementationFile=T42Document.cpp
+BaseClass=CDocument
+Filter=N
+VirtualFilter=DC
+LastObject=ID_WINDOW_AUTOSAVELAYOUT
+
+[CLS:CSplitBar]
+Type=0
+HeaderFile=t42view.h
+ImplementationFile=t42view.cpp
+BaseClass=CStatic
+Filter=W
+LastObject=CSplitBar
+VirtualFilter=WC
+
+[CLS:CLocalCtl]
+Type=0
+HeaderFile=t42view.h
+ImplementationFile=t42view.cpp
+BaseClass=CRichTalkCtl
+Filter=W
+LastObject=CLocalCtl
+VirtualFilter=WC
+
+[CLS:CRemoteCtl]
+Type=0
+HeaderFile=t42view.h
+ImplementationFile=t42view.cpp
+BaseClass=CRichTalkCtl
+Filter=W
+LastObject=CRemoteCtl
+VirtualFilter=WC
+
+[ACL:IDR_T42FRAME]
+Type=1
+Class=?
+Command1=ID_EDIT_COPY
+Command2=ID_SLEEP_SLEEP
+Command3=ID_EDIT_PASTE
+Command4=ID_EDIT_COPY
+Command5=ID_EDIT_PASTE
+CommandCount=5
+
+[DLG:IDD_ANNOUNCE]
+Type=1
+Class=T42AnnounceDlg
+ControlCount=11
+Control1=IDOK,button,1342242817
+Control2=IDC_SECRETARY,button,1342251008
+Control3=IDCANCEL,button,1342242816
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_CALLEE,static,1342308480
+Control6=IDC_TTY,static,1342308354
+Control7=IDC_STATIC,static,1342308352
+Control8=IDC_STATIC,static,1342308352
+Control9=IDC_CALLER,static,1342308482
+Control10=IDC_NOTHERE,button,1073741824
+Control11=IDC_REFUSE,button,1073741824
+
+[CLS:T42AnnounceDlg]
+Type=0
+HeaderFile=T42AnnounceDlg.h
+ImplementationFile=T42AnnounceDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=IDC_CALLEE
+VirtualFilter=dWC
+
+[MNU:IDM_POPUPS]
+Type=1
+Class=CT42Dlg
+Command1=ID_TRAY_T42
+Command2=ID_TRAY_AWAY
+Command3=ID_TRAY_SHOWMAINWINDOW
+Command4=ID_TRAY_OPTIONS
+Command5=ID_TRAY_EXIT
+Command6=ID_CALLLOG_CALLBACK
+Command7=ID_CALLLOG_DELETE
+Command8=ID_CALLLOG_SAVETOFILE
+Command9=ID_CALLLOG_MARKASNEW
+Command10=ID_CALLLOG_MARKASPROCESSED
+Command11=ID_CALLLOG_EMPTYLOG
+CommandCount=11
+
+[DLG:IDD_OPTIONS_SOUNDS]
+Type=1
+Class=CSoundsPage
+ControlCount=16
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_T42BELL,combobox,1344340290
+Control3=IDC_T42BELL_BROWSE,button,1342246720
+Control4=IDC_STATIC,static,1342177296
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_T42PROMPT,combobox,1344340290
+Control7=IDC_T42PROMPT_BROWSE,button,1342246720
+Control8=IDC_T42PROMPT_LOOP,button,1342242819
+Control9=IDC_STATIC,static,1342177296
+Control10=IDC_STATIC,static,1342308352
+Control11=IDC_T42WAKE,combobox,1344340290
+Control12=IDC_T42WAKE_BROWSE,button,1342246720
+Control13=IDC_STATIC,static,1342177296
+Control14=IDC_T42BELL_PLAY,button,1342246720
+Control15=IDC_T42PROMPT_PLAY,button,1342246720
+Control16=IDC_T42WAKE_PLAY,button,1342246720
+
+[CLS:CSoundsPage]
+Type=0
+HeaderFile=SoundsPage.h
+ImplementationFile=SoundsPage.cpp
+BaseClass=CPropertyPage
+Filter=D
+VirtualFilter=idWC
+LastObject=CSoundsPage
+
+[DLG:IDD_OPTIONS_FONTS]
+Type=1
+Class=CFontsPage
+ControlCount=16
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_FORMATNAME,listbox,1352728833
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_FACES,combobox,1344340227
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_FONTSIZE,combobox,1344340034
+Control7=IDC_BOLD,button,1342242819
+Control8=IDC_ITALIC,button,1342242819
+Control9=IDC_UNDERLINE,button,1342242819
+Control10=IDC_STRIKEOUT,button,1342242819
+Control11=IDC_CHARSET,combobox,1344340227
+Control12=IDC_FORECOLOR,button,1342242827
+Control13=IDC_BACKCOLOR,button,1342242827
+Control14=IDC_SAMPLE,RICHEDIT,1476510084
+Control15=IDC_STATIC,static,1342177296
+Control16=IDC_TIP,static,1342308352
+
+[CLS:CFontsPage]
+Type=0
+HeaderFile=FontsPage.h
+ImplementationFile=FontsPage.cpp
+BaseClass=CPropertyPage
+Filter=D
+LastObject=CFontsPage
+VirtualFilter=idWC
+
+[CLS:CColorButton]
+Type=0
+HeaderFile=ColorButton.h
+ImplementationFile=ColorButton.cpp
+BaseClass=CButton
+Filter=W
+LastObject=CColorButton
+VirtualFilter=BWC
+
+[DLG:IDD_OPTIONS_SECRETARY]
+Type=1
+Class=CSecretaryPage
+ControlCount=16
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_GREETING,edit,1352732868
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_DOBYTELIMIT,button,1342242819
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_BYTELIMIT,edit,1350639744
+Control7=IDC_CHARSPIN,msctls_updown32,1342177463
+Control8=IDC_DOTIMELIMIT,button,1342242819
+Control9=IDC_STATIC,static,1342308352
+Control10=IDC_TIMELIMIT,edit,1350639744
+Control11=IDC_TIMESPIN,msctls_updown32,1342177463
+Control12=IDC_DOWINLIMIT,button,1342242819
+Control13=IDC_STATIC,static,1342308352
+Control14=IDC_WINLIMIT,edit,1350639744
+Control15=IDC_WINSPIN,msctls_updown32,1342177463
+Control16=IDC_STATIC,static,1342177296
+
+[CLS:CSecretaryPage]
+Type=0
+HeaderFile=SecretaryPage.h
+ImplementationFile=SecretaryPage.cpp
+BaseClass=CPropertyPage
+Filter=D
+LastObject=CSecretaryPage
+VirtualFilter=idWC
+
+[DLG:IDD_OPTIONS_GENERAL]
+Type=1
+Class=CGeneralPage
+ControlCount=4
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_NTALKPORT,edit,1350631568
+Control3=IDC_NTALKPORTSPIN,msctls_updown32,1342177332
+Control4=IDC_STATIC,static,1342308352
+
+[CLS:CGeneralPage]
+Type=0
+HeaderFile=GeneralPage.h
+ImplementationFile=GeneralPage.cpp
+BaseClass=CPropertyPage
+Filter=D
+LastObject=IDC_NTALKPORTSPIN
+VirtualFilter=idWC
+
diff --git a/T42.cpp b/T42.cpp
new file mode 100644
index 0000000..9388d62
--- a/dev/null
+++ b/T42.cpp
@@ -0,0 +1,468 @@
+// T42.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42Dlg.h"
+
+#include "T42Frame.h"
+#include "T42Document.h"
+#include "T42View.h"
+
+#include "SoundsPage.h"
+#include "FontsPage.h"
+#include "SecretaryPage.h"
+#include "GeneralPage.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42App
+
+BEGIN_MESSAGE_MAP(CT42App, CWinApp)
+ //{{AFX_MSG_MAP(CT42App)
+ //}}AFX_MSG
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42App construction
+
+CT42App::CT42App()
+ : m_T42STimeLimit(0,0,2,0),
+ m_T42SBytesLimit(2048),
+ m_T42SWinLimit(10)
+{
+ m_maxT42Callees = 20;
+ m_maxT42Callers = 20;
+ m_bt42AutosaveLayout = FALSE;
+ m_nT42Calls = m_t42Call = -1;
+ m_pT42Dlg = NULL;
+ memset(&m_fmtT42Local,0,sizeof(m_fmtT42Local));
+ memset(&m_fmtT42Remote,0,sizeof(m_fmtT42Remote));
+ memset(&m_fmtT42System,0,sizeof(m_fmtT42System));
+ m_crT42LocalBG=RGB(255,255,255);
+ m_crT42RemoteBG=RGB(255,255,192);
+ m_bAwayOnScreenSaver = TRUE;
+ m_T42LinesBusy = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CT42App object
+
+CT42App theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42App initialization
+
+BOOL CT42App::InitInstance()
+{
+ if (!AfxSocketInit())
+ {
+ AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
+ return FALSE;
+ }
+
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+ SetRegistryKey(IDS_REGISTRYKEY);
+ m_HelpFile = m_pszHelpFilePath;
+ m_HelpFile+=">Standard";
+ m_pszHelpFilePath=(LPCTSTR)m_HelpFile;
+
+ m_pTemplate = new CMultiDocTemplate(IDR_T42FRAME,
+ RUNTIME_CLASS(T42Document),
+ RUNTIME_CLASS(T42Frame),
+ RUNTIME_CLASS(T42View)
+ );
+ AddDocTemplate(m_pTemplate);
+
+ Initialize();
+ LoadSettings();
+
+ if(!OpenT42CallsLog()){
+ AfxMessageBox(IDS_CALLOG_OPEN_FAILED,MB_OK|MB_ICONSTOP);
+ return FALSE;
+ }
+
+CT42Dlg dlg;
+ m_pMainWnd = &dlg;
+ m_pT42Dlg = &dlg;
+ dlg.DoModal();
+ m_pT42Dlg = NULL;
+
+ SaveSettings();
+
+ if(!CloseT42CallsLog())
+ AfxMessageBox(IDS_CALLOG_CLOSE_FAILED,MB_OK|MB_ICONSTOP);
+
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
+
+BOOL CT42App::LastCallee(LPCTSTR callee)
+{
+POSITION p = m_t42Callees.Find(callee);
+ if(p){
+ m_t42Callees.RemoveAt(p);
+ m_t42Callees.AddHead(callee);
+ return FALSE;
+ }
+ m_t42Callees.AddHead(callee);
+ while(m_t42Callees.GetCount()>m_maxT42Callees)
+ m_t42Callees.RemoveTail();
+ return TRUE;
+}
+
+void CT42App::SaveSettings()
+{
+ WriteProfileInt("Settings","AwayOnScreenSaver",m_bAwayOnScreenSaver);
+
+ Klever::SaveStringList(m_t42Callees,"T42HotList");
+ Klever::SaveStringList(m_t42Callers,"T42Callers");
+ WriteProfileInt("T42Window","AutosaveLayout",m_bt42AutosaveLayout);
+ WriteProfileInt("Settings","T42MaxCallers",m_maxT42Callers);
+ WriteProfileInt("Settings","T42MaxCallees",m_maxT42Callees);
+ WriteProfileString("Settings","T42CallsLog",m_t42CallsFile);
+ WriteProfileInt("Settings","T42TalkPort",m_T42TalkPort);
+
+ WriteProfileString("Sounds","T42Bell",m_sndT42Bell);
+ WriteProfileString("Sounds","T42Prompt",m_sndT42Prompt);
+ WriteProfileInt("Sounds","T42PromptLoop",m_bT42PromptLoop);
+ WriteProfileString("Sounds","T42Wake",m_sndT42Wake);
+
+ Klever::WriteProfileString("Secretary","T42Greeting",m_T42SGreeting);
+ WriteProfileInt("Secretary","T42BytesLimit",m_T42SBytesLimit);
+ WriteProfileInt("Secretary","T42TimeLimit",m_T42STimeLimit.GetTotalSeconds());
+ WriteProfileInt("Secretary","T42WinLimit",m_T42SWinLimit);
+
+ WriteProfileInt("Fonts","T42LocalBG",m_crT42LocalBG);
+ WriteProfileInt("Fonts","T42RemoteBG",m_crT42RemoteBG);
+ WriteProfileBinary("Fonts","T42Local",(LPBYTE)&m_fmtT42Local,sizeof(m_fmtT42Local));
+ WriteProfileBinary("Fonts","T42Remote",(LPBYTE)&m_fmtT42Remote,sizeof(m_fmtT42Remote));
+ WriteProfileBinary("Fonts","T42System",(LPBYTE)&m_fmtT42System,sizeof(m_fmtT42System));
+
+ FlushT42CallsLog();
+}
+
+void CT42App::LoadSettings()
+{
+ m_bAwayOnScreenSaver = GetProfileInt("Settings","AwayOnScreenSaver",m_bAwayOnScreenSaver);
+
+ Klever::LoadStringList(m_t42Callees,"T42HotList");
+ Klever::LoadStringList(m_t42Callers,"T42Callers");
+ m_bt42AutosaveLayout = GetProfileInt("T42Window","AutosaveLayout",m_bt42AutosaveLayout);
+ m_maxT42Callers = GetProfileInt("Settings","T42MaxCallers",m_maxT42Callers);
+ m_maxT42Callees = GetProfileInt("Settings","T42MaxCallees",m_maxT42Callees);
+ m_t42CallsFile = GetProfileString("Settings","T42CallsLog",m_t42CallsFile);
+ m_T42TalkPort = GetProfileInt("Settings","T42TalkPort",m_T42TalkPort);
+
+ m_sndT42Bell = GetProfileString("Sounds","T42Bell",m_sndT42Bell);
+ m_sndT42Prompt = GetProfileString("Sounds","T42Prompt",m_sndT42Prompt);
+ m_bT42PromptLoop = GetProfileInt("Sounds","T42PromptLoop",m_bT42PromptLoop);
+ m_sndT42Wake = GetProfileString("Sounds","T42Wake",m_sndT42Wake);
+
+ m_T42SGreeting = Klever::GetProfileString("Secretary","T42Greeting",m_T42SGreeting);
+ m_T42SBytesLimit = GetProfileInt("Secretary","T42BytesLimit",m_T42SBytesLimit);
+ m_T42STimeLimit = CTimeSpan(GetProfileInt("Secretary","T42TimeLimit",m_T42STimeLimit.GetTotalSeconds()));
+ m_T42SWinLimit = GetProfileInt("Secretary","T42WinLimit",m_T42SWinLimit);
+
+ m_crT42LocalBG = GetProfileInt("Fonts","T42LocalBG",m_crT42LocalBG);
+ m_crT42RemoteBG = GetProfileInt("Fonts","T42RemoteBG",m_crT42RemoteBG);
+LPBYTE pdata;
+UINT pbytes;
+ if(GetProfileBinary("Fonts","T42Local",&pdata,&pbytes)){
+ if(pbytes==sizeof(m_fmtT42Local))
+ memmove(&m_fmtT42Local,pdata,sizeof(m_fmtT42Local));
+ delete pdata;
+ }
+ if(GetProfileBinary("Fonts","T42Remote",&pdata,&pbytes)){
+ if(pbytes==sizeof(m_fmtT42Remote))
+ memmove(&m_fmtT42Remote,pdata,sizeof(m_fmtT42Remote));
+ delete pdata;
+ }
+ if(GetProfileBinary("Fonts","T42System",&pdata,&pbytes)){
+ if(pbytes==sizeof(m_fmtT42System))
+ memmove(&m_fmtT42System,pdata,sizeof(m_fmtT42System));
+ delete pdata;
+ }
+}
+
+BOOL CT42App::LastCaller(LPCTSTR caller)
+{
+POSITION p = m_t42Callers.Find(caller);
+ if(p){
+ m_t42Callers.RemoveAt(p);
+ m_t42Callers.AddHead(caller);
+ return FALSE;
+ }
+ m_t42Callers.AddHead(caller);
+ while(m_t42Callers.GetCount()>m_maxT42Callers)
+ m_t42Callers.RemoveTail();
+ return TRUE;
+}
+
+void CT42App::Initialize()
+{
+ VERIFY(m_T42SGreeting.LoadString(IDS_DEFAULTGREETING));
+
+ VERIFY(
+ m_sndTeaDrop.LoadString(IDS_SND_TEADROP)
+ && m_sndBoilingTeapot.LoadString(IDS_SND_BOILINGTEAPOT)
+ && m_sndTeapotWhistle.LoadString(IDS_SND_TEAPOTWHISTLE)
+ );
+
+ m_sndT42Bell = m_sndTeaDrop;
+ m_sndT42Prompt = m_sndBoilingTeapot;
+ m_bT42PromptLoop = TRUE;
+ m_sndT42Wake = m_sndTeapotWhistle;
+
+ VERIFY(m_t42CallsFile.LoadString(IDS_FILE_T42CALLS));
+CString exepa;
+ VERIFY(GetModuleFileName(m_hInstance,exepa.GetBuffer(_MAX_PATH),_MAX_PATH));
+ exepa.ReleaseBuffer();
+int bs = exepa.ReverseFind('\\');
+ VERIFY(bs>=0);
+ exepa = exepa.Left(bs);
+ m_t42CallsFile = Klever::GluePathAndFile(exepa,m_t42CallsFile);
+
+servent* se = getservbyname("ntalk","udp");
+ if(se)
+ m_T42TalkPort = ntohs(se->s_port);
+ else
+ m_T42TalkPort = 518;
+}
+
+BOOL CT42App::StartSound(LPCTSTR snd,BOOL bLoop)
+{
+ // Return TRUE if looped sound started.
+LPCSTR s = snd;
+UINT flags = SND_ASYNC|SND_NODEFAULT|SND_NOWAIT|SND_RESOURCE;
+ if(!m_sndTeaDrop.Compare(s)){
+ s = MAKEINTRESOURCE(IDW_BEEP_DROP);
+ }else if(!m_sndBoilingTeapot.Compare(s)){
+ s = MAKEINTRESOURCE(IDW_ANNOUNCE_BOILING);
+ }else if(!m_sndTeapotWhistle.Compare(s)){
+ s = MAKEINTRESOURCE(IDW_WAKE_WHISTLE);
+ }else{
+ flags&=~SND_RESOURCE;
+ flags|=SND_FILENAME;
+ }
+ if(bLoop)
+ flags|=SND_LOOP;
+ if(PlaySound(s,AfxGetInstanceHandle(),flags))
+ return bLoop;
+ MessageBeep(0xFFFFFFFF);
+ return FALSE;
+}
+
+void CT42App::StopSound(LPCTSTR snd)
+{
+LPCSTR s = snd;
+UINT flags = SND_ASYNC|SND_NODEFAULT|SND_NOWAIT|SND_RESOURCE|SND_PURGE;
+ if(!m_sndTeaDrop.Compare(s)){
+ s = MAKEINTRESOURCE(IDW_BEEP_DROP);
+ }else if(!m_sndBoilingTeapot.Compare(s)){
+ s = MAKEINTRESOURCE(IDW_ANNOUNCE_BOILING);
+ }else if(!m_sndTeapotWhistle.Compare(s)){
+ s = MAKEINTRESOURCE(IDW_WAKE_WHISTLE);
+ }else{
+ flags&=~SND_RESOURCE;
+ flags|=SND_FILENAME;
+ }
+ PlaySound(s,AfxGetInstanceHandle(),flags);
+}
+
+void CT42App::Options(CWnd* pParent)
+{
+CSoundsPage sp;
+CFontsPage fp;
+CSecretaryPage sep;
+CGeneralPage gp;
+CPropertySheet ps(IDS_TITLE_OPTIONS,pParent);
+ ps.AddPage(&gp);
+ ps.AddPage(&fp);
+ ps.AddPage(&sp);
+ ps.AddPage(&sep);
+
+ gp.m_ntalkPort = m_T42TalkPort;
+
+ sp.m_T42Bell = m_sndT42Bell;
+ sp.m_T42Prompt = m_sndT42Prompt;
+ sp.m_bT42PromptLoop = m_bT42PromptLoop;
+ sp.m_T42Wake = m_sndT42Wake;
+
+ memmove(&fp.m_fmtT42Local.m_fmtChar,&m_fmtT42Local,sizeof(fp.m_fmtT42Local.m_fmtChar));
+ memmove(&fp.m_fmtT42Remote.m_fmtChar,&m_fmtT42Remote,sizeof(fp.m_fmtT42Remote.m_fmtChar));
+ memmove(&fp.m_fmtT42System.m_fmtChar,&m_fmtT42System,sizeof(fp.m_fmtT42System.m_fmtChar));
+ fp.m_fmtT42Local.m_bgColor=m_crT42LocalBG;
+ fp.m_fmtT42Remote.m_bgColor=m_crT42RemoteBG;
+
+ sep.m_bLimitTime = m_T42STimeLimit.GetTotalSeconds()?TRUE:FALSE;
+ sep.m_limitTime = m_T42STimeLimit.GetTotalSeconds()/60;
+ sep.m_bLimitBytes = m_T42SBytesLimit?TRUE:FALSE;
+ sep.m_limitBytes = m_T42SBytesLimit;
+ sep.m_Greeting = m_T42SGreeting;
+ sep.m_limitWin = m_T42SWinLimit;
+ sep.m_bLimitWin = m_T42SWinLimit?TRUE:FALSE;
+
+ if(ps.DoModal()==IDOK){
+ m_T42TalkPort = gp.m_ntalkPort;
+
+ m_sndT42Bell = sp.m_T42Bell;
+ m_sndT42Prompt = sp.m_T42Prompt;
+ m_bT42PromptLoop = sp.m_bT42PromptLoop;
+ m_sndT42Wake = sp.m_T42Wake;
+
+ memmove(&m_fmtT42Local,&fp.m_fmtT42Local.m_fmtChar,sizeof(m_fmtT42Local));
+ memmove(&m_fmtT42Remote,&fp.m_fmtT42Remote.m_fmtChar,sizeof(m_fmtT42Remote));
+ memmove(&m_fmtT42System,&fp.m_fmtT42System.m_fmtChar,sizeof(m_fmtT42System));
+ m_crT42LocalBG=fp.m_fmtT42Local.m_bgColor;
+ m_crT42RemoteBG=fp.m_fmtT42Remote.m_bgColor;
+
+ m_T42STimeLimit = CTimeSpan(sep.m_bLimitTime?sep.m_limitTime*60:0);
+ m_T42SBytesLimit = sep.m_bLimitBytes?sep.m_limitBytes:0;
+ m_T42SWinLimit = sep.m_bLimitWin?sep.m_limitWin:0;
+ m_T42SGreeting = sep.m_Greeting;
+ }
+}
+
+BOOL CT42App::OpenT42CallsLog()
+{
+ if(!m_T42Calls.Open(m_t42CallsFile,FALSE)){
+ if(!m_T42Calls.Create(m_t42CallsFile))
+ return FALSE;
+ FlushT42CallsLog();
+ }
+ return TRUE;
+}
+
+BOOL CT42App::CloseT42CallsLog()
+{
+ return m_T42Calls.Close();
+}
+
+LONG CT42App::GetT42Calls()
+{
+ if(m_nT42Calls<0){
+ m_nT42Calls=0;
+ m_t42Call = -1;
+ if(!m_T42Calls.GoFirst())
+ return 0;
+ m_nT42Calls++;
+ while(m_T42Calls.GoNext())
+ m_nT42Calls++;
+ }
+ return m_nT42Calls;
+}
+
+BOOL CT42App::GetT42Call(LONG call,CT42CallLogEntry& entry)
+{
+LONG calls = GetT42Calls();
+ if(calls<=0)
+ return FALSE;
+ call = calls-call-1;
+ if(call<0 || calls<=call)
+ return FALSE;
+ if(m_t42Call<0){
+ if(call<(calls/2)){
+ VERIFY(m_T42Calls.GoFirst());
+ m_t42Call=0;
+ }else{
+ VERIFY(m_T42Calls.GoLast());
+ m_t42Call=calls-1;
+ }
+ }
+ if(call<m_t42Call){
+ while(call<m_t42Call){
+ VERIFY(m_T42Calls.GoPrev());
+ m_t42Call--;
+ }
+ }else if(call>m_t42Call){
+ while(call>m_t42Call){
+ VERIFY(m_T42Calls.GoNext());
+ m_t42Call++;
+ }
+ }
+ ASSERT(call==m_t42Call);
+CTime ct;
+ VERIFY(m_T42Calls.GetThis(ct,entry));
+ ASSERT(ct==entry.m_Time);
+ return TRUE;
+}
+
+BOOL CT42App::AddT42Call(CT42CallLogEntry& entry)
+{
+ m_t42Call=-1;
+ if(GetT42Calls()<=0){
+ if(m_T42Calls.Add(entry.m_Time,entry)){
+ FlushT42CallsLog();
+ ASSERT(!m_nT42Calls);
+ m_nT42Calls++;
+ ASSERT(m_pT42Dlg);
+ m_pT42Dlg->OnAddT42Call();
+ return TRUE;
+ }
+ return FALSE;
+ }
+CT42CallLogEntry cle;
+CTimeSpan inc(0,0,0,1);
+ while(m_T42Calls.Lookup(entry.m_Time,cle))
+ entry.m_Time+=inc;
+ if(m_T42Calls.Add(entry.m_Time,entry)){
+ FlushT42CallsLog();
+ m_nT42Calls++;
+ ASSERT(m_pT42Dlg);
+ m_pT42Dlg->OnAddT42Call();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL CT42App::DelT42Call(CTime& time)
+{
+ m_t42Call=-1;
+ if(GetT42Calls()<=0)
+ return FALSE;
+ if(m_T42Calls.Delete(time)){
+ FlushT42CallsLog();
+ m_nT42Calls--;
+ ASSERT(m_pT42Dlg);
+ m_pT42Dlg->OnDelT42Call();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CT42App::UpdateT42Call(CT42CallLogEntry& entry)
+{
+ m_t42Call=-1;
+#ifdef _DEBUG
+CT42CallLogEntry cle;
+ ASSERT(m_T42Calls.Lookup(entry.m_Time,cle));
+#endif
+ m_T42Calls.Add(entry.m_Time,entry);
+ FlushT42CallsLog();
+ return TRUE;
+}
+
+void CT42App::FlushT42CallsLog()
+{
+ m_T42Calls.m_BT.m_File->Flush();
+}
diff --git a/T42.h b/T42.h
new file mode 100644
index 0000000..b330a9f
--- a/dev/null
+++ b/T42.h
@@ -0,0 +1,83 @@
+// T42.h : main header file for the T42 application
+//
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42App:
+// See T42.cpp for the implementation of this class
+//
+
+class CT42Dlg;
+class CT42App : public CWinApp
+{
+public:
+ void FlushT42CallsLog();
+ CString m_HelpFile;
+ UINT m_T42TalkPort;
+ UINT m_T42LinesBusy;
+ BOOL m_bAwayOnScreenSaver;
+ BOOL UpdateT42Call(CT42CallLogEntry& entry);
+ CT42Dlg* m_pT42Dlg;
+ BOOL DelT42Call(CTime& time);
+ BOOL AddT42Call(CT42CallLogEntry& entry);
+ LONG m_nT42Calls;
+ LONG GetT42Calls();
+ BOOL GetT42Call(LONG call,CT42CallLogEntry& entry);
+ LONG m_t42Call;
+ BOOL CloseT42CallsLog();
+ BOOL OpenT42CallsLog();
+ CString m_t42CallsFile;
+ CT42CallLog m_T42Calls;
+ CString m_T42SGreeting;
+ CTimeSpan m_T42STimeLimit;
+ UINT m_T42SWinLimit;
+ UINT m_T42SBytesLimit;
+ COLORREF m_crT42LocalBG;
+ COLORREF m_crT42RemoteBG;
+ CHARFORMAT m_fmtT42System;
+ CHARFORMAT m_fmtT42Remote;
+ CHARFORMAT m_fmtT42Local;
+ void Options(CWnd* pParent=NULL);
+ void StopSound(LPCTSTR snd);
+ BOOL StartSound(LPCTSTR snd,BOOL bLoop = FALSE);
+ void Initialize();
+ CString m_sndTeapotWhistle;
+ CString m_sndBoilingTeapot;
+ CString m_sndTeaDrop;
+ CString m_sndT42Wake;
+ BOOL m_bT42PromptLoop;
+ CString m_sndT42Prompt;
+ CString m_sndT42Bell;
+ BOOL m_bt42AutosaveLayout;
+ UINT m_maxT42Callers;
+ CStringList m_t42Callers;
+ BOOL LastCaller(LPCTSTR caller);
+ void LoadSettings();
+ void SaveSettings();
+ UINT m_maxT42Callees;
+ BOOL LastCallee(LPCTSTR callee);
+ CStringList m_t42Callees;
+ CDocTemplate* m_pTemplate;
+ CT42App();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CT42App)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CT42App)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/T42.mak b/T42.mak
new file mode 100644
index 0000000..d3ef99f
--- a/dev/null
+++ b/T42.mak
@@ -0,0 +1,1691 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+!IF "$(CFG)" == ""
+CFG=Install - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to Install - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "T42 - Win32 Debug" && "$(CFG)" != "T42 - Win32 Pure" &&\
+ "$(CFG)" != "T42 - Win32 Static" && "$(CFG)" != "Install - Win32 Debug" &&\
+ "$(CFG)" != "Install - Win32 Pure" && "$(CFG)" != "Install - Win32 Static" &&\
+ "$(CFG)" != "Install - Win32 Canned"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "T42.mak" CFG="Install - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "T42 - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "T42 - Win32 Pure" (based on "Win32 (x86) Application")
+!MESSAGE "T42 - Win32 Static" (based on "Win32 (x86) Application")
+!MESSAGE "Install - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "Install - Win32 Pure" (based on "Win32 (x86) Application")
+!MESSAGE "Install - Win32 Static" (based on "Win32 (x86) Application")
+!MESSAGE "Install - Win32 Canned" (based on "Win32 (x86) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "Install - Win32 Canned"
+CPP=cl.exe
+RSC=rc.exe
+MTL=mktyplib.exe
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+TargetName=T42
+# End Custom Macros
+
+ALL : "$(OUTDIR)\T42.exe" "$(OUTDIR)\T42.ex_" "$(OUTDIR)\T42.hlp"\
+ "$(OUTDIR)\T42.cnt" "$(OUTDIR)\T42.hl_" "$(OUTDIR)\T42.cn_"
+
+CLEAN :
+ -@erase "$(INTDIR)\CalleeDlg.obj"
+ -@erase "$(INTDIR)\ColorButton.obj"
+ -@erase "$(INTDIR)\FontsPage.obj"
+ -@erase "$(INTDIR)\GeneralPage.obj"
+ -@erase "$(INTDIR)\RegEx.obj"
+ -@erase "$(INTDIR)\SecretaryPage.obj"
+ -@erase "$(INTDIR)\SoundsPage.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\T42.cn_"
+ -@erase "$(INTDIR)\T42.cnt"
+ -@erase "$(INTDIR)\T42.hl_"
+ -@erase "$(INTDIR)\T42.hlp"
+ -@erase "$(INTDIR)\T42.obj"
+ -@erase "$(INTDIR)\T42.pch"
+ -@erase "$(INTDIR)\T42.res"
+ -@erase "$(INTDIR)\T42AnnounceDlg.obj"
+ -@erase "$(INTDIR)\T42Dlg.obj"
+ -@erase "$(INTDIR)\T42Document.obj"
+ -@erase "$(INTDIR)\T42Frame.obj"
+ -@erase "$(INTDIR)\T42Secretary.obj"
+ -@erase "$(INTDIR)\T42View.obj"
+ -@erase "$(INTDIR)\vc40.idb"
+ -@erase "$(INTDIR)\vc40.pdb"
+ -@erase "$(OUTDIR)\T42.ex_"
+ -@erase "$(OUTDIR)\T42.exe"
+ -@erase "$(OUTDIR)\T42.ilk"
+ -@erase "$(OUTDIR)\T42.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
+ /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yu"stdafx.h" /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/T42.res" /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/T42.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386
+LINK32_FLAGS=/nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/T42.pdb" /debug /machine:I386 /out:"$(OUTDIR)/T42.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\CalleeDlg.obj" \
+ "$(INTDIR)\ColorButton.obj" \
+ "$(INTDIR)\FontsPage.obj" \
+ "$(INTDIR)\GeneralPage.obj" \
+ "$(INTDIR)\RegEx.obj" \
+ "$(INTDIR)\SecretaryPage.obj" \
+ "$(INTDIR)\SoundsPage.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\T42.obj" \
+ "$(INTDIR)\T42.res" \
+ "$(INTDIR)\T42AnnounceDlg.obj" \
+ "$(INTDIR)\T42Dlg.obj" \
+ "$(INTDIR)\T42Document.obj" \
+ "$(INTDIR)\T42Frame.obj" \
+ "$(INTDIR)\T42Secretary.obj" \
+ "$(INTDIR)\T42View.obj"
+
+"$(OUTDIR)\T42.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+# Begin Custom Build
+OutDir=.\Debug
+TargetName=T42
+InputPath=.\Debug\T42.exe
+SOURCE=$(InputPath)
+
+"$(OutDir)\$(TargetName).ex_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ compress $(OutDir)\$(TargetName).exe $(OutDir)\$(TargetName).ex_
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "T42___Wi"
+# PROP BASE Intermediate_Dir "T42___Wi"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "RELEASE"
+# PROP Intermediate_Dir "RELEASE"
+# PROP Target_Dir ""
+OUTDIR=.\RELEASE
+INTDIR=.\RELEASE
+# Begin Custom Macros
+OutDir=.\RELEASE
+TargetName=T42
+# End Custom Macros
+
+ALL : "$(OUTDIR)\T42.exe" "$(OUTDIR)\T42.ex_" "$(OUTDIR)\T42.hlp"\
+ "$(OUTDIR)\T42.cnt" "$(OUTDIR)\T42.hl_" "$(OUTDIR)\T42.cn_"
+
+CLEAN :
+ -@erase "$(INTDIR)\CalleeDlg.obj"
+ -@erase "$(INTDIR)\ColorButton.obj"
+ -@erase "$(INTDIR)\FontsPage.obj"
+ -@erase "$(INTDIR)\GeneralPage.obj"
+ -@erase "$(INTDIR)\RegEx.obj"
+ -@erase "$(INTDIR)\SecretaryPage.obj"
+ -@erase "$(INTDIR)\SoundsPage.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\T42.cn_"
+ -@erase "$(INTDIR)\T42.cnt"
+ -@erase "$(INTDIR)\T42.hl_"
+ -@erase "$(INTDIR)\T42.hlp"
+ -@erase "$(INTDIR)\T42.obj"
+ -@erase "$(INTDIR)\T42.pch"
+ -@erase "$(INTDIR)\T42.res"
+ -@erase "$(INTDIR)\T42AnnounceDlg.obj"
+ -@erase "$(INTDIR)\T42Dlg.obj"
+ -@erase "$(INTDIR)\T42Document.obj"
+ -@erase "$(INTDIR)\T42Frame.obj"
+ -@erase "$(INTDIR)\T42Secretary.obj"
+ -@erase "$(INTDIR)\T42View.obj"
+ -@erase "$(OUTDIR)\T42.ex_"
+ -@erase "$(OUTDIR)\T42.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yu"stdafx.h" /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\RELEASE/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/T42.res" /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/T42.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386
+LINK32_FLAGS=/nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/T42.pdb" /machine:I386 /out:"$(OUTDIR)/T42.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\CalleeDlg.obj" \
+ "$(INTDIR)\ColorButton.obj" \
+ "$(INTDIR)\FontsPage.obj" \
+ "$(INTDIR)\GeneralPage.obj" \
+ "$(INTDIR)\RegEx.obj" \
+ "$(INTDIR)\SecretaryPage.obj" \
+ "$(INTDIR)\SoundsPage.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\T42.obj" \
+ "$(INTDIR)\T42.res" \
+ "$(INTDIR)\T42AnnounceDlg.obj" \
+ "$(INTDIR)\T42Dlg.obj" \
+ "$(INTDIR)\T42Document.obj" \
+ "$(INTDIR)\T42Frame.obj" \
+ "$(INTDIR)\T42Secretary.obj" \
+ "$(INTDIR)\T42View.obj"
+
+"$(OUTDIR)\T42.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+# Begin Custom Build
+OutDir=.\RELEASE
+TargetName=T42
+InputPath=.\RELEASE\T42.exe
+SOURCE=$(InputPath)
+
+"$(OutDir)\$(TargetName).ex_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ compress $(OutDir)\$(TargetName).exe $(OutDir)\$(TargetName).ex_
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "T42___W0"
+# PROP BASE Intermediate_Dir "T42___W0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "RELEAST"
+# PROP Intermediate_Dir "RELEAST"
+# PROP Target_Dir ""
+OUTDIR=.\RELEAST
+INTDIR=.\RELEAST
+# Begin Custom Macros
+OutDir=.\RELEAST
+TargetName=T42
+# End Custom Macros
+
+ALL : "$(OUTDIR)\T42.exe" "$(OUTDIR)\T42.ex_" "$(OUTDIR)\T42.hlp"\
+ "$(OUTDIR)\T42.cnt" "$(OUTDIR)\T42.hl_" "$(OUTDIR)\T42.cn_"
+
+CLEAN :
+ -@erase "$(INTDIR)\CalleeDlg.obj"
+ -@erase "$(INTDIR)\ColorButton.obj"
+ -@erase "$(INTDIR)\FontsPage.obj"
+ -@erase "$(INTDIR)\GeneralPage.obj"
+ -@erase "$(INTDIR)\RegEx.obj"
+ -@erase "$(INTDIR)\SecretaryPage.obj"
+ -@erase "$(INTDIR)\SoundsPage.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\T42.cn_"
+ -@erase "$(INTDIR)\T42.cnt"
+ -@erase "$(INTDIR)\T42.hl_"
+ -@erase "$(INTDIR)\T42.hlp"
+ -@erase "$(INTDIR)\T42.obj"
+ -@erase "$(INTDIR)\T42.pch"
+ -@erase "$(INTDIR)\T42.res"
+ -@erase "$(INTDIR)\T42AnnounceDlg.obj"
+ -@erase "$(INTDIR)\T42Dlg.obj"
+ -@erase "$(INTDIR)\T42Document.obj"
+ -@erase "$(INTDIR)\T42Frame.obj"
+ -@erase "$(INTDIR)\T42Secretary.obj"
+ -@erase "$(INTDIR)\T42View.obj"
+ -@erase "$(OUTDIR)\T42.ex_"
+ -@erase "$(OUTDIR)\T42.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /c
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yu"stdafx.h" /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\RELEAST/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/T42.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/T42.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386
+LINK32_FLAGS=/nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/T42.pdb" /machine:I386 /out:"$(OUTDIR)/T42.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\CalleeDlg.obj" \
+ "$(INTDIR)\ColorButton.obj" \
+ "$(INTDIR)\FontsPage.obj" \
+ "$(INTDIR)\GeneralPage.obj" \
+ "$(INTDIR)\RegEx.obj" \
+ "$(INTDIR)\SecretaryPage.obj" \
+ "$(INTDIR)\SoundsPage.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\T42.obj" \
+ "$(INTDIR)\T42.res" \
+ "$(INTDIR)\T42AnnounceDlg.obj" \
+ "$(INTDIR)\T42Dlg.obj" \
+ "$(INTDIR)\T42Document.obj" \
+ "$(INTDIR)\T42Frame.obj" \
+ "$(INTDIR)\T42Secretary.obj" \
+ "$(INTDIR)\T42View.obj"
+
+"$(OUTDIR)\T42.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+# Begin Custom Build
+OutDir=.\RELEAST
+TargetName=T42
+InputPath=.\RELEAST\T42.exe
+SOURCE=$(InputPath)
+
+"$(OutDir)\$(TargetName).ex_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ compress $(OutDir)\$(TargetName).exe $(OutDir)\$(TargetName).ex_
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "Install - Win32 Debug"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Install\Debug"
+# PROP BASE Intermediate_Dir "Install\Debug"
+# PROP BASE Target_Dir "Install"
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Install\Debug"
+# PROP Intermediate_Dir "Install\Debug"
+# PROP Target_Dir "Install"
+OUTDIR=.\Install\Debug
+INTDIR=.\Install\Debug
+
+ALL : "T42 - Win32 Debug" "$(OUTDIR)\Install.exe"
+
+CLEAN :
+ -@erase "$(INTDIR)\install.obj"
+ -@erase "$(INTDIR)\Install.res"
+ -@erase "$(INTDIR)\vc40.idb"
+ -@erase "$(INTDIR)\vc40.pdb"
+ -@erase "$(OUTDIR)\Install.exe"
+ -@erase "$(OUTDIR)\Install.ilk"
+ -@erase "$(OUTDIR)\Install.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
+ /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/Install.pch" /YX /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Install\Debug/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Install.res" /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Install.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 version.lib /nologo /subsystem:windows /debug /machine:I386
+LINK32_FLAGS=version.lib /nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/Install.pdb" /debug /machine:I386 /out:"$(OUTDIR)/Install.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\install.obj" \
+ "$(INTDIR)\Install.res"
+
+"$(OUTDIR)\Install.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Install - Win32 Pure"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Install\Pure"
+# PROP BASE Intermediate_Dir "Install\Pure"
+# PROP BASE Target_Dir "Install"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Install\Pure"
+# PROP Intermediate_Dir "Install\Pure"
+# PROP Target_Dir "Install"
+OUTDIR=.\Install\Pure
+INTDIR=.\Install\Pure
+
+ALL : "T42 - Win32 Pure" "$(OUTDIR)\Install.exe"
+
+CLEAN :
+ -@erase "$(INTDIR)\install.obj"
+ -@erase "$(INTDIR)\Install.res"
+ -@erase "$(OUTDIR)\Install.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_MBCS" /Fp"$(INTDIR)/Install.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Install\Pure/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Install.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Install.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib /nologo /subsystem:windows /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib version.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/Install.pdb" /machine:I386 /out:"$(OUTDIR)/Install.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\install.obj" \
+ "$(INTDIR)\Install.res"
+
+"$(OUTDIR)\Install.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Install - Win32 Static"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Install\Static"
+# PROP BASE Intermediate_Dir "Install\Static"
+# PROP BASE Target_Dir "Install"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Install\Static"
+# PROP Intermediate_Dir "Install\Static"
+# PROP Target_Dir "Install"
+OUTDIR=.\Install\Static
+INTDIR=.\Install\Static
+
+ALL : "T42 - Win32 Static" "$(OUTDIR)\Install.exe"
+
+CLEAN :
+ -@erase "$(INTDIR)\install.obj"
+ -@erase "$(INTDIR)\Install.res"
+ -@erase "$(OUTDIR)\Install.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "STATI_K" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_MBCS" /D "STATI_K" /Fp"$(INTDIR)/Install.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Install\Static/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "STATI_K"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Install.res" /d "NDEBUG" /d "STATI_K"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Install.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib /nologo /subsystem:windows /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib version.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/Install.pdb" /machine:I386 /out:"$(OUTDIR)/Install.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\install.obj" \
+ "$(INTDIR)\Install.res"
+
+"$(OUTDIR)\Install.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Install - Win32 Canned"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Install\Canned"
+# PROP BASE Intermediate_Dir "Install\Canned"
+# PROP BASE Target_Dir "Install"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Install\Canned"
+# PROP Intermediate_Dir "Install\Canned"
+# PROP Target_Dir "Install"
+OUTDIR=.\Install\Canned
+INTDIR=.\Install\Canned
+
+ALL : "$(OUTDIR)\Install.exe"
+
+CLEAN :
+ -@erase "$(INTDIR)\install.obj"
+ -@erase "$(INTDIR)\Install.res"
+ -@erase "$(OUTDIR)\Install.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "K_ANNED" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_MBCS" /D "K_ANNED" /Fp"$(INTDIR)/Install.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Install\Canned/
+CPP_SBRS=.\.
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "K_ANNED"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Install.res" /d "NDEBUG" /d "K_ANNED"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Install.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib /nologo /subsystem:windows /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib version.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/Install.pdb" /machine:I386 /out:"$(OUTDIR)/Install.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\install.obj" \
+ "$(INTDIR)\Install.res"
+
+"$(OUTDIR)\Install.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "T42 - Win32 Debug"
+# Name "T42 - Win32 Pure"
+# Name "T42 - Win32 Static"
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42.cpp
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+DEP_CPP_T42_C=\
+ ".\ColorButton.h"\
+ ".\FontsPage.h"\
+ ".\GeneralPage.h"\
+ ".\SecretaryPage.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\SoundsPage.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Dlg.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+"$(INTDIR)\T42.obj" : $(SOURCE) $(DEP_CPP_T42_C) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+DEP_CPP_T42_C=\
+ ".\ColorButton.h"\
+ ".\FontsPage.h"\
+ ".\GeneralPage.h"\
+ ".\SecretaryPage.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\SoundsPage.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Dlg.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+"$(INTDIR)\T42.obj" : $(SOURCE) $(DEP_CPP_T42_C) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+DEP_CPP_T42_C=\
+ ".\ColorButton.h"\
+ ".\FontsPage.h"\
+ ".\GeneralPage.h"\
+ ".\SecretaryPage.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\SoundsPage.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Dlg.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+"$(INTDIR)\T42.obj" : $(SOURCE) $(DEP_CPP_T42_C) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42Dlg.cpp
+DEP_CPP_T42DL=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42AnnounceDlg.h"\
+ ".\T42CallLog.h"\
+ ".\T42Dlg.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42Secretary.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42Dlg.obj" : $(SOURCE) $(DEP_CPP_T42DL) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42Dlg.obj" : $(SOURCE) $(DEP_CPP_T42DL) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42Dlg.obj" : $(SOURCE) $(DEP_CPP_T42DL) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+DEP_CPP_STDAF=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+# ADD CPP /Yc"stdafx.h"
+
+BuildCmds= \
+ $(CPP) /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
+ /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yc"stdafx.h" /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c $(SOURCE) \
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+"$(INTDIR)\T42.pch" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+# ADD BASE CPP /Yc"stdafx.h"
+# ADD CPP /Yc"stdafx.h"
+
+BuildCmds= \
+ $(CPP) /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yc"stdafx.h" /Fo"$(INTDIR)/" /c\
+ $(SOURCE) \
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+"$(INTDIR)\T42.pch" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+# ADD BASE CPP /Yc"stdafx.h"
+# ADD CPP /Yc"stdafx.h"
+
+BuildCmds= \
+ $(CPP) /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS"\
+ /Fp"$(INTDIR)/T42.pch" /Yc"stdafx.h" /Fo"$(INTDIR)/" /c $(SOURCE) \
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+"$(INTDIR)\T42.pch" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42.rc
+DEP_RSC_T42_R=\
+ ".\res\fullcup.ico"\
+ ".\res\idr_flip.ico"\
+ ".\res\idr_full.ico"\
+ ".\res\idr_t42f.ico"\
+ ".\res\T42-Beep.wav"\
+ ".\res\T42-Boiling.wav"\
+ ".\res\T42-Whistle.wav"\
+ ".\res\T42.ico"\
+ ".\res\T42.rc2"\
+ ".\res\t42calln.ico"\
+ ".\res\t42callp.ico"\
+ ".\shared-data\browse-icon.ico"\
+ ".\shared-data\klever-background.bmp"\
+ ".\shared-data\play-icon.ico"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42.res" : $(SOURCE) $(DEP_RSC_T42_R) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42.res" : $(SOURCE) $(DEP_RSC_T42_R) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42.res" : $(SOURCE) $(DEP_RSC_T42_R) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\help\T42.hpj
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+# Begin Custom Build - Making help file...
+OutDir=.\Debug
+ProjDir=.
+TargetName=T42
+InputPath=.\help\T42.hpj
+
+BuildCmds= \
+ "$(ProjDir)\makehelp.bat" \
+ compress $(OutDir)\$(TargetName).hlp $(OutDir)\$(TargetName).hl_ \
+ compress $(OutDir)\$(TargetName).cnt $(OutDir)\$(TargetName).cn_ \
+
+
+"$(OutDir)\$(TargetName).hlp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).cnt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).hl_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).cn_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+# Begin Custom Build - Making help file...
+OutDir=.\RELEASE
+ProjDir=.
+TargetName=T42
+InputPath=.\help\T42.hpj
+
+BuildCmds= \
+ "$(ProjDir)\makehelp.bat" \
+ compress $(OutDir)\$(TargetName).hlp $(OutDir)\$(TargetName).hl_ \
+ compress $(OutDir)\$(TargetName).cnt $(OutDir)\$(TargetName).cn_ \
+
+
+"$(OutDir)\$(TargetName).hlp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).cnt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).hl_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).cn_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+# Begin Custom Build - Making help file...
+OutDir=.\RELEAST
+ProjDir=.
+TargetName=T42
+InputPath=.\help\T42.hpj
+
+BuildCmds= \
+ "$(ProjDir)\makehelp.bat" \
+ compress $(OutDir)\$(TargetName).hlp $(OutDir)\$(TargetName).hl_ \
+ compress $(OutDir)\$(TargetName).cnt $(OutDir)\$(TargetName).cn_ \
+
+
+"$(OutDir)\$(TargetName).hlp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).cnt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).hl_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+
+"$(OutDir)\$(TargetName).cn_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ $(BuildCmds)
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42Frame.cpp
+DEP_CPP_T42FR=\
+ ".\CalleeDlg.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\RegEx.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42Frame.obj" : $(SOURCE) $(DEP_CPP_T42FR) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42Frame.obj" : $(SOURCE) $(DEP_CPP_T42FR) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42Frame.obj" : $(SOURCE) $(DEP_CPP_T42FR) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42View.cpp
+DEP_CPP_T42VI=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Frame.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42View.obj" : $(SOURCE) $(DEP_CPP_T42VI) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42View.obj" : $(SOURCE) $(DEP_CPP_T42VI) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42View.obj" : $(SOURCE) $(DEP_CPP_T42VI) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\CalleeDlg.cpp
+DEP_CPP_CALLE=\
+ ".\CalleeDlg.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\CalleeDlg.obj" : $(SOURCE) $(DEP_CPP_CALLE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\CalleeDlg.obj" : $(SOURCE) $(DEP_CPP_CALLE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\CalleeDlg.obj" : $(SOURCE) $(DEP_CPP_CALLE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42Document.cpp
+DEP_CPP_T42DO=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42Document.obj" : $(SOURCE) $(DEP_CPP_T42DO) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42Document.obj" : $(SOURCE) $(DEP_CPP_T42DO) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42Document.obj" : $(SOURCE) $(DEP_CPP_T42DO) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42AnnounceDlg.cpp
+DEP_CPP_T42AN=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42AnnounceDlg.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42AnnounceDlg.obj" : $(SOURCE) $(DEP_CPP_T42AN) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42AnnounceDlg.obj" : $(SOURCE) $(DEP_CPP_T42AN) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42AnnounceDlg.obj" : $(SOURCE) $(DEP_CPP_T42AN) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SoundsPage.cpp
+DEP_CPP_SOUND=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\SoundsPage.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\SoundsPage.obj" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\SoundsPage.obj" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\SoundsPage.obj" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FontsPage.cpp
+DEP_CPP_FONTS=\
+ ".\ColorButton.h"\
+ ".\FontsPage.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\FontsPage.obj" : $(SOURCE) $(DEP_CPP_FONTS) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\FontsPage.obj" : $(SOURCE) $(DEP_CPP_FONTS) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\FontsPage.obj" : $(SOURCE) $(DEP_CPP_FONTS) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ColorButton.cpp
+DEP_CPP_COLOR=\
+ ".\ColorButton.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\ColorButton.obj" : $(SOURCE) $(DEP_CPP_COLOR) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\ColorButton.obj" : $(SOURCE) $(DEP_CPP_COLOR) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\ColorButton.obj" : $(SOURCE) $(DEP_CPP_COLOR) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SecretaryPage.cpp
+DEP_CPP_SECRE=\
+ ".\SecretaryPage.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\SecretaryPage.obj" : $(SOURCE) $(DEP_CPP_SECRE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\SecretaryPage.obj" : $(SOURCE) $(DEP_CPP_SECRE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\SecretaryPage.obj" : $(SOURCE) $(DEP_CPP_SECRE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\T42Secretary.cpp
+DEP_CPP_T42SE=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\T42Document.h"\
+ ".\T42Frame.h"\
+ ".\T42Secretary.h"\
+ ".\T42View.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\T42Secretary.obj" : $(SOURCE) $(DEP_CPP_T42SE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\T42Secretary.obj" : $(SOURCE) $(DEP_CPP_T42SE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\T42Secretary.obj" : $(SOURCE) $(DEP_CPP_T42SE) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\GeneralPage.cpp
+DEP_CPP_GENER=\
+ ".\GeneralPage.h"\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+
+"$(INTDIR)\GeneralPage.obj" : $(SOURCE) $(DEP_CPP_GENER) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+
+"$(INTDIR)\GeneralPage.obj" : $(SOURCE) $(DEP_CPP_GENER) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+
+"$(INTDIR)\GeneralPage.obj" : $(SOURCE) $(DEP_CPP_GENER) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=".\shared-code\RegEx.cpp"
+DEP_CPP_REGEX=\
+ ".\shared-code\BitSet.h"\
+ ".\shared-code\BTreendex.h"\
+ ".\shared-code\Dynamide.h"\
+ ".\shared-code\FindIFace.h"\
+ ".\shared-code\kHelpers.h"\
+ ".\shared-code\LRUCache.h"\
+ ".\shared-code\RegEx.h"\
+ ".\shared-code\SNMPeer.h"\
+ ".\shared-code\SNMPExtDll.h"\
+ ".\shared-code\SNMPOIDs.h"\
+ ".\stdafx.h"\
+ ".\T42CallLog.h"\
+ ".\talkd.h"\
+
+
+!IF "$(CFG)" == "T42 - Win32 Debug"
+
+# ADD CPP /Yu"../stdafx.h"
+
+"$(INTDIR)\RegEx.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+ $(CPP) /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
+ /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yu"../stdafx.h" /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Pure"
+
+# ADD CPP /Yu"../stdafx.h"
+
+"$(INTDIR)\RegEx.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+ $(CPP) /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yu"../stdafx.h" /Fo"$(INTDIR)/" /c\
+ $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "T42 - Win32 Static"
+
+# ADD CPP /Yu"../stdafx.h"
+
+"$(INTDIR)\RegEx.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)"\
+ "$(INTDIR)\T42.pch"
+ $(CPP) /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
+ "_MBCS" /Fp"$(INTDIR)/T42.pch" /Yu"../stdafx.h" /Fo"$(INTDIR)/" /c $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "Install - Win32 Debug"
+# Name "Install - Win32 Pure"
+# Name "Install - Win32 Static"
+# Name "Install - Win32 Canned"
+
+!IF "$(CFG)" == "Install - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "Install - Win32 Pure"
+
+!ELSEIF "$(CFG)" == "Install - Win32 Static"
+
+!ELSEIF "$(CFG)" == "Install - Win32 Canned"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\Install\Install.rc
+DEP_RSC_INSTA=\
+ ".\Install\Custom.rch"\
+ ".\shared-data\install-icon.ico"\
+
+
+!IF "$(CFG)" == "Install - Win32 Debug"
+
+
+"$(INTDIR)\Install.res" : $(SOURCE) $(DEP_RSC_INSTA) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/Install.res" /i "Install" /d "_DEBUG" /d\
+ "_AFXDLL" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Install - Win32 Pure"
+
+
+"$(INTDIR)\Install.res" : $(SOURCE) $(DEP_RSC_INSTA) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/Install.res" /i "Install" /d "NDEBUG"\
+ $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Install - Win32 Static"
+
+
+"$(INTDIR)\Install.res" : $(SOURCE) $(DEP_RSC_INSTA) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/Install.res" /i "Install" /d "NDEBUG" /d\
+ "STATI_K" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Install - Win32 Canned"
+
+
+"$(INTDIR)\Install.res" : $(SOURCE) $(DEP_RSC_INSTA) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/Install.res" /i "Install" /d "NDEBUG" /d\
+ "K_ANNED" $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Install\install.cpp
+DEP_CPP_INSTAL=\
+ ".\shared-code\install.h"\
+
+
+!IF "$(CFG)" == "Install - Win32 Debug"
+
+
+"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTAL) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Install - Win32 Pure"
+
+
+"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTAL) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Install - Win32 Static"
+
+
+"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTAL) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "Install - Win32 Canned"
+
+
+"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTAL) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "T42"
+
+!IF "$(CFG)" == "Install - Win32 Debug"
+
+"T42 - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\T42.mak" CFG="T42 - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "Install - Win32 Pure"
+
+"T42 - Win32 Pure" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\T42.mak" CFG="T42 - Win32 Pure"
+
+!ELSEIF "$(CFG)" == "Install - Win32 Static"
+
+"T42 - Win32 Static" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\T42.mak" CFG="T42 - Win32 Static"
+
+!ELSEIF "$(CFG)" == "Install - Win32 Canned"
+
+!ENDIF
+
+# End Project Dependency
+# End Target
+# End Project
+################################################################################
diff --git a/T42.rc b/T42.rc
new file mode 100644
index 0000000..b51806e
--- a/dev/null
+++ b/T42.rc
@@ -0,0 +1,837 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\T42.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\T42.ico"
+IDR_T42FRAME ICON DISCARDABLE "res\\IDR_T42F.ico"
+IDI_FULLCUP ICON DISCARDABLE "res\\fullcup.ico"
+IDR_FULLT42 ICON DISCARDABLE "res\\IDR_FULL.ico"
+IDI_BROWSE ICON DISCARDABLE "shared-data/browse-icon.ico"
+IDI_T42CALLNEW ICON DISCARDABLE "res\\T42calln.ico"
+IDI_T42CALLPROCESSED ICON DISCARDABLE "res\\T42callp.ico"
+IDR_FLIPPEDCUP ICON DISCARDABLE "res\\IDR_FLIP.ico"
+IDI_PREPLAY ICON DISCARDABLE "shared-data/play-icon.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 194, 78
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About T42"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "T42, Version 1.5",IDC_STATIC,37,10,119,8,SS_NOPREFIX
+ LTEXT "Copyright © 1998,2002 Klever Group",IDC_STATIC,37,25,119,8
+ ICON IDR_MAINFRAME,IDC_STATIC,7,34,18,20
+ ICON IDR_FLIPPEDCUP,IDC_STATIC,166,34,18,20
+ DEFPUSHBUTTON "OK",IDOK,81,40,32,14,WS_GROUP
+ PUSHBUTTON "http://www.klever.net/",IDC_KLEVERNET,107,59,80,12
+END
+
+IDD_T42_DIALOG DIALOGEX 0, 0, 221, 200
+STYLE DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE | WS_EX_CONTEXTHELP |
+ WS_EX_APPWINDOW
+CAPTION " Tea For Two "
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ CTEXT "On &Call:",IDC_STATIC,7,7,93,56,0,WS_EX_DLGMODALFRAME |
+ WS_EX_CLIENTEDGE
+ COMBOBOX IDC_ONCALL,13,19,81,76,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CTEXT "When &Away:",IDC_STATIC,13,33,81,8
+ COMBOBOX IDC_ONCALLAWAY,13,43,81,76,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "Calls",IDC_CALLS,"SysListView32",LVS_REPORT | WS_BORDER |
+ WS_TABSTOP,7,66,207,67
+ CONTROL "Recorded Message..",IDC_PREVIEW,"RICHEDIT",WS_VSCROLL |
+ WS_TABSTOP | 0xc184,7,134,207,59
+ PUSHBUTTON "&Tea",IDC_TALK,173,7,41,13
+ PUSHBUTTON "&Options",IDC_OPTIONS,173,21,41,13
+ PUSHBUTTON "E&xit",IDOK,173,35,41,13
+ PUSHBUTTON "&Help",ID_HELP,173,49,41,13
+ DEFPUSHBUTTON "",IDCANCEL,0,0,6,6,NOT WS_VISIBLE
+ CONTROL "A&way",IDC_AWAY,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE |
+ BS_MULTILINE | WS_TABSTOP,101,7,41,56,
+ WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
+ WS_EX_STATICEDGE
+END
+
+IDD_REMOTE DIALOGEX 0, 0, 153, 111
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CAPTION
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+CAPTION " It's party time!"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "&Dear ",IDC_STATIC,7,9,18,8
+ COMBOBOX IDC_CALLEE,29,7,117,56,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "yes, you on &tty ",IDC_STATIC,41,23,48,8
+ COMBOBOX IDC_TTY,98,21,48,79,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "I'd love to have a cup of tea with you. How about right now?",
+ IDC_STATIC,19,36,112,28
+ LTEXT "Yours,",IDC_STATIC,7,67,22,8
+ COMBOBOX IDC_CALLER,46,73,100,30,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",IDOK,18,90,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,84,90,50,14
+END
+
+IDD_T42VIEW DIALOG DISCARDABLE 0, 0, 185, 93
+STYLE DS_3DLOOK | WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "",IDC_SPLIT,"Static",SS_SIMPLE | SS_NOTIFY,93,1,8,91
+END
+
+IDD_ANNOUNCE DIALOGEX 0, 0, 141, 139
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_CAPTION
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+CAPTION " It's a party and you're invited!"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "&Yes, I'd appreciate some milk",IDOK,7,81,127,14
+ PUSHBUTTON "Not now, have a cup of tea with my &secretary",
+ IDC_SECRETARY,7,96,127,21,BS_MULTILINE
+ PUSHBUTTON "&No, thanks, I'm out to cofee house.",IDCANCEL,7,118,
+ 127,14
+ LTEXT "Dear ",IDC_STATIC,7,7,18,8
+ LTEXT "..",IDC_CALLEE,27,7,107,8,SS_NOPREFIX
+ RTEXT "..",IDC_TTY,7,16,127,10
+ LTEXT "I'd love to have a cup of tea with you. How about right now?",
+ IDC_STATIC,15,28,112,19
+ LTEXT "Yours,",IDC_STATIC,15,50,21,8
+ RTEXT "..",IDC_CALLER,7,59,127,20,SS_NOPREFIX
+ PUSHBUTTON "",IDC_NOTHERE,0,132,6,6,NOT WS_VISIBLE | NOT WS_TABSTOP
+ PUSHBUTTON "",IDC_REFUSE,7,132,6,6,NOT WS_VISIBLE | NOT WS_TABSTOP
+END
+
+IDD_OPTIONS_SOUNDS DIALOG DISCARDABLE 0, 0, 210, 154
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Sounds"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "&Bell in T42 conversation window:",IDC_STATIC,7,5,83,16
+ COMBOBOX IDC_T42BELL,90,5,83,65,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Bell Browse",IDC_T42BELL_BROWSE,175,5,13,13,BS_ICON |
+ BS_CENTER | BS_VCENTER
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,25,196,1
+ LTEXT "&Prompt sound alert:",IDC_STATIC,7,30,83,8
+ COMBOBOX IDC_T42PROMPT,90,30,83,65,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Prompt Browse",IDC_T42PROMPT_BROWSE,175,30,13,13,
+ BS_ICON | BS_CENTER | BS_VCENTER
+ CONTROL "&Loop sound",IDC_T42PROMPT_LOOP,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,36,40,53,8
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,50,196,1
+ LTEXT "&Wake-up sound alert:",IDC_STATIC,7,55,83,16
+ COMBOBOX IDC_T42WAKE,90,55,83,65,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Wake Browse",IDC_T42WAKE_BROWSE,175,55,13,13,BS_ICON |
+ BS_CENTER | BS_VCENTER
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,75,196,1
+ PUSHBUTTON "Bell Play",IDC_T42BELL_PLAY,190,5,13,13,BS_ICON |
+ BS_CENTER | BS_VCENTER
+ PUSHBUTTON "Prompt Play",IDC_T42PROMPT_PLAY,190,30,13,13,BS_ICON |
+ BS_CENTER | BS_VCENTER
+ PUSHBUTTON "Wake Play",IDC_T42WAKE_PLAY,190,55,13,13,BS_ICON |
+ BS_CENTER | BS_VCENTER
+END
+
+IDD_OPTIONS_FONTS DIALOG DISCARDABLE 0, 0, 210, 154
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Format"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "F&ormat:",IDC_STATIC,7,5,24,8
+ LISTBOX IDC_FORMATNAME,7,15,60,85,LBS_NOINTEGRALHEIGHT |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Font &face:",IDC_STATIC,70,5,33,8
+ COMBOBOX IDC_FACES,70,15,90,72,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Font &size:",IDC_STATIC,163,5,31,8
+ COMBOBOX IDC_FONTSIZE,163,15,40,72,CBS_DROPDOWN | CBS_AUTOHSCROLL |
+ WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Bold",IDC_BOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 70,30,39,10
+ CONTROL "&Italic",IDC_ITALIC,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,115,30,31,10
+ CONTROL "&Underline",IDC_UNDERLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,157,30,46,10
+ CONTROL "Strike&out",IDC_STRIKEOUT,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,70,43,44,10
+ COMBOBOX IDC_CHARSET,115,41,88,59,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Foreground color",IDC_FORECOLOR,"Button",BS_OWNERDRAW |
+ WS_TABSTOP,70,56,64,14
+ CONTROL "&Background color",IDC_BACKCOLOR,"Button",BS_OWNERDRAW |
+ WS_TABSTOP,139,56,64,14
+ CONTROL "Sample",IDC_SAMPLE,"RICHEDIT",WS_DISABLED | WS_TABSTOP |
+ 0xc184,70,72,133,28
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,105,196,1
+ LTEXT "..",IDC_TIP,7,110,196,39
+END
+
+IDD_OPTIONS_SECRETARY DIALOG DISCARDABLE 0, 0, 210, 154
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Secretary"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "&Greeting message:",IDC_STATIC,7,7,60,8
+ EDITTEXT IDC_GREETING,7,16,196,61,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
+ LTEXT "After greeting, stop recording when",IDC_STATIC,7,77,
+ 111,8
+ CONTROL "&more than",IDC_DOBYTELIMIT,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,85,47,12
+ LTEXT "&characters entered, or",IDC_STATIC,96,87,70,8
+ EDITTEXT IDC_BYTELIMIT,55,85,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_CHARSPIN,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS,84,85,11,12
+ CONTROL "&time limit of",IDC_DOTIMELIMIT,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,7,98,47,12
+ LTEXT "min&utes exceeded.",IDC_STATIC,96,100,63,8
+ EDITTEXT IDC_TIMELIMIT,55,98,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_TIMESPIN,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS,85,98,10,12
+ CONTROL "Stop automatically &accepting calls when",
+ IDC_DOWINLIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,
+ 115,140,12
+ LTEXT "calls in &progress",IDC_STATIC,97,129,54,8
+ EDITTEXT IDC_WINLIMIT,55,127,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_WINSPIN,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS,85,127,10,12
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,113,196,1
+END
+
+IDD_OPTIONS_GENERAL DIALOG DISCARDABLE 0, 0, 210, 154
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "General"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "T42 '&ntalk' daemon listening on port ",IDC_STATIC,7,7,
+ 114,8
+ EDITTEXT IDC_NTALKPORT,123,5,80,12,ES_LOWERCASE | ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_NTALKPORTSPIN,"msctls_updown32",
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,193,5,10,
+ 12
+ LTEXT "Note: you will need to restart T42 if you change ntalk demon port number.",
+ IDC_STATIC,40,20,163,20
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,5,0,0
+ PRODUCTVERSION 1,5,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Klever Group (http://www.klever.net/)\0"
+ VALUE "FileDescription", "T42, unix talk/ntalk implementation\0"
+ VALUE "FileVersion", "1, 5, 0, 0\0"
+ VALUE "InternalName", "T42\0"
+ VALUE "LegalCopyright", "Copyright © 1998, 2002 Klever Group (http://www.klever.net/)\0"
+ VALUE "LegalTrademarks", "Klever Group (http://www.klever.net/)\0"
+ VALUE "OriginalFilename", "T42.EXE\0"
+ VALUE "ProductName", "T42\0"
+ VALUE "ProductVersion", "1, 5, 0, 0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 187
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 71
+ END
+
+ IDD_T42_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 214
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 193
+ END
+
+ IDD_REMOTE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 146
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 104
+ END
+
+ IDD_ANNOUNCE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 134
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 132
+ END
+
+ IDD_OPTIONS_SOUNDS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 203
+ VERTGUIDE, 90
+ VERTGUIDE, 175
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_OPTIONS_FONTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 203
+ VERTGUIDE, 67
+ VERTGUIDE, 70
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 149
+ HORZGUIDE, 100
+ END
+
+ IDD_OPTIONS_SECRETARY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 203
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 147
+ HORZGUIDE, 77
+ END
+
+ IDD_OPTIONS_GENERAL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 203
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 149
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_T42FRAME MENU DISCARDABLE
+BEGIN
+ POPUP "&Tea"
+ BEGIN
+ MENUITEM "Remote &user", ID_TALK_REMOTEUSER
+ MENUITEM "&Close connection", ID_TALK_ABORT
+ MENUITEM "&Re-connect", ID_TALK_RECONNECT
+ MENUITEM SEPARATOR
+ MENUITEM "&Save", ID_TEA_SAVE
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_TALK_CLOSE
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Copy\tCtrl-INS", ID_EDIT_COPY
+ MENUITEM "&Paste\tShift-INS", ID_EDIT_PASTE
+ END
+ POPUP "&Sleep"
+ BEGIN
+ MENUITEM "&Sleep\tCtrl-S", ID_SLEEP_SLEEP
+ MENUITEM SEPARATOR
+ MENUITEM "Sleep on &minimize", ID_SLEEP_SLEEPONMINIMIZE
+ MENUITEM "Minimi&ze on sleep", ID_SLEEP_MINIMIZEONSLEEP
+ POPUP "&Wake-up action"
+ BEGIN
+ MENUITEM "Make &sound", ID_SLEEP_WAKEUPACTION_MAKESOUND
+
+ MENUITEM "&Pop-up", ID_SLEEP_WAKEUPACTION_POPUP
+
+ END
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "Split e&qually", ID_WINDOW_SPLITEQUALLY
+ MENUITEM "&Save layout", ID_WINDOW_SAVELAYOUT
+ MENUITEM "&Autosave layout", ID_WINDOW_AUTOSAVELAYOUT
+ MENUITEM SEPARATOR
+ MENUITEM "&Horizontal split", ID_WINDOW_HORIZONTALSPLIT
+ MENUITEM "&Vertical split", ID_WINDOW_VERTICALSPLIT
+ MENUITEM SEPARATOR
+ MENUITEM "&Hide on minimize", ID_WINDOW_HIDEINTRAYONMINIMIZE
+
+ END
+END
+
+IDM_POPUPS MENU DISCARDABLE
+BEGIN
+ POPUP "Tray"
+ BEGIN
+ MENUITEM "Order some &tea", ID_TRAY_T42
+ MENUITEM "&Away", ID_TRAY_AWAY
+ MENUITEM "Show main &window", ID_TRAY_SHOWMAINWINDOW
+ MENUITEM "&Options", ID_TRAY_OPTIONS
+ MENUITEM "E&xit", ID_TRAY_EXIT
+ END
+ POPUP "Call Log"
+ BEGIN
+ MENUITEM "&Call back", ID_CALLLOG_CALLBACK
+ MENUITEM "&Delete", ID_CALLLOG_DELETE
+ MENUITEM "&Save to file..", ID_CALLLOG_SAVETOFILE
+ MENUITEM SEPARATOR
+ MENUITEM "Mark as &new", ID_CALLLOG_MARKASNEW
+ MENUITEM "Mark as &processed", ID_CALLLOG_MARKASPROCESSED
+ MENUITEM SEPARATOR
+ MENUITEM "&Empty Log", ID_CALLLOG_EMPTYLOG
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_T42FRAME ACCELERATORS DISCARDABLE
+BEGIN
+ "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_SLEEP_SLEEP, VIRTKEY, CONTROL, NOINVERT
+ "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_REMOTE DLGINIT
+BEGIN
+ IDC_TTY, 0x403, 5, 0
+0x7474, 0x3079, "\000"
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7079, 0x0030,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7679, 0x0030,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x6179, 0x0030,
+ IDC_TTY, 0x403, 5, 0
+0x7474, 0x3179, "\000"
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7079, 0x0031,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7679, 0x0031,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x6179, 0x0031,
+ IDC_TTY, 0x403, 5, 0
+0x7474, 0x3279, "\000"
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7079, 0x0032,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7679, 0x0032,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x6179, 0x0032,
+ IDC_TTY, 0x403, 5, 0
+0x7474, 0x3379, "\000"
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7079, 0x0033,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7679, 0x0033,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x6179, 0x0033,
+ IDC_TTY, 0x403, 5, 0
+0x7474, 0x3479, "\000"
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7079, 0x0034,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x7679, 0x0034,
+ IDC_TTY, 0x403, 6, 0
+0x7474, 0x6179, 0x0034,
+ 0
+END
+
+IDD_T42_DIALOG DLGINIT
+BEGIN
+ IDC_ONCALL, 0x403, 7, 0
+0x7250, 0x6d6f, 0x7470, "\000"
+ IDC_ONCALL, 0x403, 10, 0
+0x6553, 0x7263, 0x7465, 0x7261, 0x0079,
+ IDC_ONCALL, 0x403, 9, 0
+0x6f4e, 0x2074, 0x6568, 0x6572, "\000"
+ IDC_ONCALL, 0x403, 7, 0
+0x6552, 0x7566, 0x6573, "\000"
+ IDC_ONCALL, 0x403, 7, 0
+0x6749, 0x6f6e, 0x6572, "\000"
+ IDC_ONCALLAWAY, 0x403, 7, 0
+0x7250, 0x6d6f, 0x7470, "\000"
+ IDC_ONCALLAWAY, 0x403, 10, 0
+0x6553, 0x7263, 0x7465, 0x7261, 0x0079,
+ IDC_ONCALLAWAY, 0x403, 9, 0
+0x6f4e, 0x2074, 0x6568, 0x6572, "\000"
+ IDC_ONCALLAWAY, 0x403, 7, 0
+0x6552, 0x7566, 0x6573, "\000"
+ IDC_ONCALLAWAY, 0x403, 7, 0
+0x6749, 0x6f6e, 0x6572, "\000"
+ 0
+END
+
+IDD_OPTIONS_SOUNDS DLGINIT
+BEGIN
+ IDC_T42BELL, 0x403, 11, 0
+0x7428, 0x6165, 0x642d, 0x6f72, 0x2970, "\000"
+ IDC_T42PROMPT, 0x403, 17, 0
+0x6228, 0x696f, 0x696c, 0x676e, 0x742d, 0x6165, 0x6f70, 0x2974, "\000"
+ IDC_T42WAKE, 0x403, 17, 0
+0x7428, 0x6165, 0x6f70, 0x2d74, 0x6877, 0x7369, 0x6c74, 0x2965, "\000"
+ 0
+END
+
+IDD_OPTIONS_FONTS DLGINIT
+BEGIN
+ IDC_FONTSIZE, 0x403, 2, 0
+0x0036,
+ IDC_FONTSIZE, 0x403, 2, 0
+0x0038,
+ IDC_FONTSIZE, 0x403, 2, 0
+0x0039,
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3031, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3131, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3231, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3431, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3631, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3831, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3232, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3432, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3632, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3233, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3633, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3834, "\000"
+ IDC_FONTSIZE, 0x403, 3, 0
+0x3237, "\000"
+ 0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_BACK BITMAP DISCARDABLE "shared-data/klever-background.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// WAVE
+//
+
+IDW_BEEP_DROP WAVE DISCARDABLE "res\\T42-beep.wav"
+IDW_ANNOUNCE_BOILING WAVE DISCARDABLE "res\\T42-boiling.wav"
+IDW_WAKE_WHISTLE WAVE DISCARDABLE "res\\T42-whistle.wav"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ABOUTBOX "&About T42..."
+ IDS_ERR_MALFORMEDREMOTE "Malformed remote name."
+ IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed."
+ ID_INDICATOR_DATE "Date"
+ IDS_STATUS_RESOLVING "Looking up remote host address.."
+ IDS_ERR_REMOTERESOLVEFAILED "Remote lookup failed: %s"
+ IDS_ERR_CTLCREATEFAILED "Failed to create control socket: %s"
+ IDS_ERR_CTLBINDFAILED "Failed to bind control socket: %s"
+ IDS_ERR_CTLGETFAILED "Failed to get control socket name: %s"
+ IDS_ERR_TCPCREATEFAILED "Failed to create conversation socket: %s"
+ IDS_ERR_TCPBINDFAILED "Failed to bind conversation socket: %s"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CTL_BADCTL "Remote didn't like out ctl address. This means you can not see this message."
+ IDR_T42FRAME "Tea For Two"
+ IDS_CTL_UNKNOWNERROR "Remote talk daemon seems to be talking different language.."
+ IDS_ERR_ANNOUNCEFAILED "Failed to page remote user."
+ IDS_ERR_LEAVINVITEFAILED
+ "Failed to leave an invitation on local talk daemon."
+ IDS_ERR_TCPACCEPTFAILED "Failed to accept remote connection: %s"
+ IDS_STATUS_ANNOUNCING "Ringing your party.."
+ IDS_ERR_CTLLDELETEFAILED
+ "Failed to clean up invitation on local machine."
+ IDS_ERR_CTLRDELETEFAILED
+ "Failed to clean up invitation on remote machine."
+ IDS_ERR_TCPERROR "Error on conversation socket: %s"
+ IDS_STATUS_ESTABLISHED "Connection established."
+ IDS_STATUS_CONNECTIONCLOSED "Connection closed."
+ IDS_TITLE_TEAWITH "Tea with %s"
+ IDS_TITLE_TEAFORTWO "Tea For Two"
+ IDS_TITLE_OPTIONS "T42 Options"
+ IDS_SND_TEADROP "(tea-drop)"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TALK_ABORT "Close the connection\nClose"
+ ID_TALK_CLOSE "Close this window\nExit"
+ ID_WINDOW_CENTERSPLITTER "Center Splitter position"
+ ID_WINDOW_SPLITEQUALLY "Center splitterbar position\nEquisplit"
+ ID_WINDOW_SAVELAYOUT "Save window layout\nSave"
+ ID_WINDOW_AUTOSAVELAYOUT "Automatically save layout\nAutosave"
+ ID_TALK_REMOTEUSER "Issue talk request to specific user\nTea"
+ ID_WINDOW_HORIZONTALSPLIT "Make split horizontal\nHorizontal"
+ ID_WINDOW_VERTICALSPLIT "Make split vertical\nVertical"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_MRU_FIRST "Call this user\nCall"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_EDIT_COPY "Copy selection to clipboard\nCopy"
+ ID_EDIT_PASTE "Paste clipboard to remote\nPaste"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_APP_TITLE "T42"
+ AFX_IDS_IDLEMESSAGE "No connection, yet."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ERR_TCPGETFAILED "Failed to get conversation socket name: %s"
+ IDS_STATUS_LOOKUPINVITE "Looking up invitation on remote.."
+ IDS_ERR_TCPASELFAILED "Failed to select conversation socket: %s"
+ IDS_STATUS_WAITINGTOCONNECT "Waiting to connect with remote.."
+ IDS_ERR_TCPCONNECTFAILED "Failed to connect to remote: %s"
+ IDS_ERR_TCPLISTENFAILED "Listen on conversation socket failed: %s"
+ IDS_ERR_LTNASELFAILED "Failed to select listening socket: %s"
+ IDS_ERR_CTLLOOKUPFAILED "Failed to connect to remote talk daemon."
+ IDS_ERR_ANNOUNCEFAILURE "Failed to page user: %s"
+ IDS_CTL_NOTHERE "Your party isn't logged in."
+ IDS_CTL_FAILED "Remote talk daemon failed to explain the reason."
+ IDS_CTL_MACHUNKNOWN "Remote talk daemon doesn't want to talk to us."
+ IDS_CTL_PERMISSIONDENIED "Your party is refusing messages."
+ IDS_CTL_BADREQUEST "Remote talk daemon doesn't recognize our request"
+ IDS_CTL_BADVERSION "Protocol version mismatch."
+ IDS_CTL_BADADDR "Remote didn't like our address."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TALK_RECONNECT "Connect again to the same user\nReconnect"
+ ID_WINDOW_HIDEINTRAYONMINIMIZE
+ "When minimizing window hide into tray icon\nTray Minimize"
+ ID_SLEEP_SLEEP "Put window into sleep mode\nSleep"
+ ID_SLEEP_MAKESOUND "Make sound on wake-up\nWake-Alarm"
+ ID_SLEEP_POPUP "Bring window to top on wake-up\nPop-up on wake"
+ ID_SLEEP_WAKEUPACTION_MAKESOUND "Make sound when waking-up\nWake-alarm"
+ ID_SLEEP_WAKEUPACTION_POPUP
+ "Bring window to top when waking-up\nWake-popup"
+ ID_SLEEP_SLEEPONMINIMIZE
+ "Put window into sleep mode when minimizing\nMinimize-sleep"
+ ID_SLEEP_MINIMIZEONSLEEP
+ "Minimize (or hide to tray area) on sleep\nSleep-minimize"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_SND_BOILINGTEAPOT "(boiling-teapot)"
+ IDS_SND_TEAPOTWHISTLE "(teapot-whistle)"
+ IDS_TITLE_WAV "Select Sound.."
+ IDS_FILTER_WAV "Sound Files (*.wav)|*.wav||"
+ IDS_FMT_T42LOCAL "Local\nFont used for local user pane in Tea For Two conversation window."
+ IDS_FMT_T42REMOTE "Remote\nFont used for remote user pane in Tea For Two conversation window."
+ IDS_FMT_T42SYSTEM "System\nFont used for system messages. Background color is taken from appropriate window format."
+ IDS_CHARSET_AUTO "(Auto)"
+ IDS_DEFAULTGREETING "Hello, I'm just a secretary, but feel free to have a tea with me - I have my pencil ready and I'll write down what you say, unless it will take longer than %t minutes and this small piece of paper can hold only %c characters, so drink fast and wisely!\n"
+ IDS_FILENAME_T42 "Tea for %s and %s.rtf"
+ IDS_RTF_HEAD "{\\rtf1\\ansi\n\\tgraph500\\trqc\\cellx4000\\cellx8000\n\\qc\\sa100\\intbl {\\b %s } \\cell {\\b\\qc %s } \\cell\\row\n\\pard\n\\intbl\n\n"
+ IDS_FILE_T42CALLS "T42.Calls"
+ IDS_FORMAT_CALLTIME "%c"
+ IDS_FILTER_RTF "Rich Text Format (*.rtf)|*.rtf||"
+ IDS_FORMAT_CALLDURATION "%D.%H:%M:%S"
+ IDS_FORMAT_CALLTIMELONG "%#c"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_FORMAT_T42CALLHEADER
+ "---\\\nTime: %s\\\nCaller: %s\\\nCallee: %s\\\nCall Duration: %s\\\n--\\\n"
+ IDS_WSA_ENETDOWN "Network is down"
+ IDS_WSA_ECONNRESET "Connection reset by peer"
+ IDS_WSA_ECONNABORTED "Connection aborted"
+ IDS_WSA_ECONNREFUSED "Connection refused"
+ IDS_WSA_ENETUNREACH "Network is unreachable"
+ IDS_WSA_ETIMEDOUT "Connection timed out"
+ IDS_CONNECTIONCLOSED "Connection closed"
+ IDS_WSA_NODATA "Valid name, no data"
+ IDS_ERR_CONNECTIONCLOSED "Connection closed: %s"
+ IDS_WSA_HOSTNOTFOUND "Host not found"
+ IDS_KLEVERNET_URL "http://www.klever.net/"
+ IDS_RTF_DELIMITER "\n\n\\cell\n\n"
+ IDS_RTF_TAIL "\\cell\\row\n}\n"
+ IDS_FAILVALIDATE_NTALKPORT
+ "Set ntalk port to either readable representation of existing service or number between 1 and 65535."
+ IDS_CALLOG_OPEN_FAILED "Failed to open/create secretary log database."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TEA_SAVE "Save conversation as RTF file\nSave"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CALLOG_CLOSE_FAILED "Failed to gracefully close secretary log database."
+ IDS_DAEMON_FAIL "Failed to set up ntalk daemon. You may still be able to use T42 for outgoing calls if you have other talk daemon installed."
+ IDS_REGISTRYKEY "Klever Group, Inc."
+ IDS_DEFAULTCALLER "tealover"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "res\T42.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/T42AnnounceDlg.cpp b/T42AnnounceDlg.cpp
new file mode 100644
index 0000000..874a898
--- a/dev/null
+++ b/T42AnnounceDlg.cpp
@@ -0,0 +1,144 @@
+// T42AnnounceDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42AnnounceDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// T42AnnounceDlg dialog
+
+
+T42AnnounceDlg::T42AnnounceDlg(TalkCtlMessage& rq,CWnd* pParent /*=NULL*/)
+ : CDialog(T42AnnounceDlg::IDD, pParent), m_RQ(rq)
+{
+ //{{AFX_DATA_INIT(T42AnnounceDlg)
+ m_Callee = _T("");
+ m_Caller = _T("");
+ m_TTY = _T("");
+ //}}AFX_DATA_INIT
+ m_Callee = rq.m_RName;
+ m_Caller = rq.m_LName;
+ m_Caller+= '@';
+ m_Caller+= inet_ntoa(((sockaddr_in*)&rq.m_Addr)->sin_addr);
+ m_TTY = rq.m_RTTY;
+ m_asyncRequest=NULL;
+ m_timeOut = 30;
+ m_ipCaller = m_Caller;
+ m_bLooped=FALSE;
+}
+
+
+void T42AnnounceDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(T42AnnounceDlg)
+ DDX_Control(pDX, IDC_CALLEE, m_CalleeCtl);
+ DDX_Control(pDX, IDC_TTY, m_TTYCtl);
+ DDX_Control(pDX, IDOK, m_YesCtl);
+ DDX_Control(pDX, IDCANCEL, m_NotMeCtl);
+ DDX_Control(pDX, IDC_SECRETARY, m_SecretaryCtl);
+ DDX_Control(pDX, IDC_CALLER, m_CallerCtl);
+ DDX_Text(pDX, IDC_CALLEE, m_Callee);
+ DDX_Text(pDX, IDC_CALLER, m_Caller);
+ DDX_Text(pDX, IDC_TTY, m_TTY);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(T42AnnounceDlg, CDialog)
+ //{{AFX_MSG_MAP(T42AnnounceDlg)
+ ON_MESSAGE(WM_SOURCERESOLVED, OnSourceResolved)
+ ON_WM_DESTROY()
+ ON_WM_TIMER()
+ ON_BN_CLICKED(IDC_SECRETARY, OnSecretary)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// T42AnnounceDlg message handlers
+
+BOOL T42AnnounceDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_asyncRequest = WSAAsyncGetHostByAddr(m_hWnd,WM_SOURCERESOLVED,
+ (CHAR*)&((sockaddr_in*)&m_RQ.m_Addr)->sin_addr,
+ 4,AF_INET,
+ m_ResolveBuffer,sizeof(m_ResolveBuffer)
+ );
+
+CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ m_bLooped = app->StartSound(app->m_sndT42Prompt,app->m_bT42PromptLoop);
+ SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
+ SetTimer(timerTimeout,m_timeOut*1000,NULL);
+CFont* f = GetFont();
+LOGFONT lf;
+ if(f->GetLogFont(&lf)){
+ if(lf.lfWeight)
+ lf.lfWeight = 1000-lf.lfWeight;
+ else
+ lf.lfWeight = 700;
+ if(m_Font.CreateFontIndirect(&lf)){
+ m_CalleeCtl.SetFont(&m_Font);
+ m_CallerCtl.SetFont(&m_Font);
+ m_TTYCtl.SetFont(&m_Font);
+ }
+ }
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+LRESULT T42AnnounceDlg::OnSourceResolved(WPARAM,LPARAM lP)
+{
+ if(WSAGETASYNCERROR(lP)){
+ TRACE1("Failed to resolve callee's host: %ld\n",WSAGETASYNCERROR(lP));
+ return -1;
+ }
+hostent* he = (hostent*)m_ResolveBuffer;
+ m_Caller = m_RQ.m_LName;
+ m_Caller+= '@';
+ m_Caller+= he->h_name;
+ m_CallerCtl.SetWindowText(m_Caller);
+ m_asyncRequest=NULL;
+ return 0;
+}
+
+void T42AnnounceDlg::OnDestroy()
+{
+ if(m_bLooped){
+ CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ app->StopSound(app->m_sndT42Prompt);
+ }
+ m_bLooped=FALSE;
+ if(m_asyncRequest){
+ WSACancelAsyncRequest(m_asyncRequest);
+ m_asyncRequest=NULL;
+ }
+ CDialog::OnDestroy();
+}
+
+void T42AnnounceDlg::OnTimer(UINT nIDEvent)
+{
+ if(nIDEvent==timerTimeout){
+ KillTimer(timerTimeout);
+ UpdateData(TRUE);
+ // *** OnPromptTimeout?
+ EndDialog(IDC_SECRETARY);
+ }else
+ CDialog::OnTimer(nIDEvent);
+}
+
+void T42AnnounceDlg::OnSecretary()
+{
+ UpdateData(TRUE);
+ EndDialog(IDC_SECRETARY);
+}
diff --git a/T42AnnounceDlg.h b/T42AnnounceDlg.h
new file mode 100644
index 0000000..aa3aa58
--- a/dev/null
+++ b/T42AnnounceDlg.h
@@ -0,0 +1,55 @@
+// T42AnnounceDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// T42AnnounceDlg dialog
+
+class T42AnnounceDlg : public CDialog
+{
+// Construction
+public:
+ CFont m_Font;
+ LPCSTR m_hSound;
+ BOOL m_bLooped;
+ CString m_ipCaller;
+ UINT m_timeOut;
+ HANDLE m_asyncRequest;
+ CHAR m_ResolveBuffer[MAXGETHOSTSTRUCT];
+ TalkCtlMessage m_RQ;
+ T42AnnounceDlg(TalkCtlMessage& rq,CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(T42AnnounceDlg)
+ enum { IDD = IDD_ANNOUNCE };
+ CStatic m_CalleeCtl;
+ CStatic m_TTYCtl;
+ CButton m_YesCtl;
+ CButton m_NotMeCtl;
+ CButton m_SecretaryCtl;
+ CStatic m_CallerCtl;
+ CString m_Callee;
+ CString m_Caller;
+ CString m_TTY;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(T42AnnounceDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(T42AnnounceDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg LRESULT OnSourceResolved(WPARAM,LPARAM);
+ afx_msg void OnDestroy();
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnSecretary();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/T42CallLog.h b/T42CallLog.h
new file mode 100644
index 0000000..fa4a331
--- a/dev/null
+++ b/T42CallLog.h
@@ -0,0 +1,53 @@
+class CT42CallLogEntry : public CObject {
+public:
+ enum {
+ statusOk = 0, statusFailed, statusProcessed,
+ statusNone
+ };
+ UINT m_Status;
+ CTime m_Time;
+ CString m_Caller;
+ CString m_Callee;
+ CString m_TTY;
+ CTimeSpan m_Duration;
+ CString m_Message;
+
+ CT42CallLogEntry() : m_Status(statusNone) {}
+ CT42CallLogEntry(CT42CallLogEntry& src) { Copy(src); }
+
+ void Copy(const CT42CallLogEntry& src) {
+ m_Status = src.m_Status;
+ m_Time = src.m_Time;
+ m_Caller = src.m_Caller; m_Callee = src.m_Callee;
+ m_TTY = src.m_TTY;
+ m_Duration = src.m_Duration;
+ m_Message = src.m_Message;
+ }
+ CT42CallLogEntry& operator=(const CT42CallLogEntry& src) {
+ Copy(src);
+ return *this;
+ }
+
+ void Serialize(CArchive& ar) {
+ if(ar.IsStoring()){
+ ar << m_Status;
+ ar << m_Time;
+ ar << m_Caller; ar << m_Callee; ar << m_TTY;
+ ar << m_Duration;
+ ar << m_Message;
+ }else{
+ ar >> m_Status;
+ ar >> m_Time;
+ ar >> m_Caller; ar >> m_Callee; ar >> m_TTY;
+ ar >> m_Duration;
+ ar >> m_Message;
+ }
+ }
+};
+
+inline void SerializeElements(CArchive& ar, CT42CallLogEntry* pElements, int nCount) {
+ for(int tmp=0;tmp<nCount;tmp++)
+ pElements[tmp].Serialize(ar);
+}
+
+typedef Klever::CBTreendex<CTime,CT42CallLogEntry,16,512> CT42CallLog;
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 @@
+// T42Dlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42Dlg.h"
+
+#include "T42Frame.h"
+#include "T42AnnounceDlg.h"
+#include "T42Document.h"
+#include "T42Secretary.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDlg dialog used for App About
+
+class CAboutDlg : public CDialog
+{
+public:
+ CAboutDlg();
+
+// Dialog Data
+ //{{AFX_DATA(CAboutDlg)
+ enum { IDD = IDD_ABOUTBOX };
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CAboutDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ //{{AFX_MSG(CAboutDlg)
+ afx_msg void OnKlevernet();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+ //{{AFX_DATA_INIT(CAboutDlg)
+ //}}AFX_DATA_INIT
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CAboutDlg)
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+ //{{AFX_MSG_MAP(CAboutDlg)
+ ON_BN_CLICKED(IDC_KLEVERNET, OnKlevernet)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+void CAboutDlg::OnKlevernet()
+{
+CString url;
+ VERIFY(url.LoadString(IDS_KLEVERNET_URL));
+ ShellExecute(::GetDesktopWindow(),"open",url,NULL,NULL,SW_SHOWMAXIMIZED);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42Dlg dialog
+
+CT42Dlg::CT42Dlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CT42Dlg::IDD, pParent),
+ m_sizeMin(0,0)
+{
+ //{{AFX_DATA_INIT(CT42Dlg)
+ //}}AFX_DATA_INIT
+ // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
+ m_hIconEmpty = m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+ m_hIconFull = AfxGetApp()->LoadIcon(IDI_FULLCUP);
+ m_newCalls = 0;
+ m_daemonSocket = INVALID_SOCKET;
+ m_talkLifetime = CTimeSpan(0,0,3,0); // 3 mins..
+ m_trackTalkID = 1;
+ m_bmpBack.LoadBitmap(IDB_BACK);
+ m_bmpBack.GetBitmap(&m_bitmapBack);
+ m_bExiting = m_bShown = FALSE;
+ m_hExFW = NULL;
+ m_marginX = m_marginY = m_gapY = 0;
+ m_bAway = FALSE;
+ m_onCall = 0;
+ m_onCallAway = IDC_SECRETARY;
+ LoadSettings();
+}
+
+CT42Dlg::~CT42Dlg()
+{
+ SaveSettings();
+}
+
+void CT42Dlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CT42Dlg)
+ DDX_Control(pDX, IDOK, m_ExitCtl);
+ DDX_Control(pDX, IDC_TALK, m_TeaCtl);
+ DDX_Control(pDX, IDC_AWAY, m_AwayCtl);
+ DDX_Control(pDX, ID_HELP, m_HelpCtl);
+ DDX_Control(pDX, IDC_OPTIONS, m_OptionsCtl);
+ DDX_Control(pDX, IDC_ONCALLAWAY, m_OnCallAwayCtl);
+ DDX_Control(pDX, IDC_ONCALL, m_OnCallCtl);
+ DDX_Control(pDX, IDC_CALLS, m_CallsCtl);
+ DDX_Control(pDX, IDC_PREVIEW, m_PreviewCtl);
+ //}}AFX_DATA_MAP
+ if(pDX->m_bSaveAndValidate){
+ m_onCall = GetOnCtl(m_OnCallCtl);
+ m_onCallAway = GetOnCtl(m_OnCallAwayCtl);
+ }else{
+ SetOnCtl(m_onCall,m_OnCallCtl);
+ SetOnCtl(m_onCallAway,m_OnCallAwayCtl);
+ }
+}
+
+BEGIN_MESSAGE_MAP(CT42Dlg, CDialog)
+ //{{AFX_MSG_MAP(CT42Dlg)
+ ON_WM_SYSCOMMAND()
+ ON_WM_DESTROY()
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_BN_CLICKED(IDC_TALK, OnTalk)
+ ON_MESSAGE(WM_DAEMON, OnDaemon)
+ ON_WM_CREATE()
+ ON_MESSAGE(WM_TRAYICON, OnTrayIcon)
+ ON_WM_WINDOWPOSCHANGING()
+ ON_COMMAND(ID_TRAY_EXIT, OnTrayExit)
+ ON_COMMAND(ID_TRAY_OPTIONS, OnTrayOptions)
+ ON_COMMAND(ID_TRAY_SHOWMAINWINDOW, OnTrayShowmainwindow)
+ ON_COMMAND(ID_TRAY_T42, OnTrayT42)
+ ON_BN_CLICKED(IDC_OPTIONS, OnOptions)
+ ON_NOTIFY(LVN_GETDISPINFO, IDC_CALLS, OnGetdispinfoCalls)
+ ON_NOTIFY(LVN_ITEMCHANGED, IDC_CALLS, OnItemchangedCalls)
+ ON_NOTIFY(NM_RCLICK, IDC_CALLS, OnRclickCalls)
+ ON_COMMAND(ID_CALLLOG_CALLBACK, OnCalllogCallback)
+ ON_COMMAND(ID_CALLLOG_DELETE, OnCalllogDelete)
+ ON_COMMAND(ID_CALLLOG_SAVETOFILE, OnCalllogSavetofile)
+ ON_COMMAND(ID_CALLLOG_EMPTYLOG, OnCalllogEmptylog)
+ ON_NOTIFY(LVN_DELETEITEM, IDC_CALLS, OnDeleteitemCalls)
+ ON_MESSAGE(WM_UPDATEPREVIEW, OnUpdatePreview)
+ ON_NOTIFY(LVN_KEYDOWN, IDC_CALLS, OnKeydownCalls)
+ ON_WM_SHOWWINDOW()
+ ON_COMMAND(ID_CALLLOG_MARKASNEW, OnCalllogMarkasnew)
+ ON_COMMAND(ID_CALLLOG_MARKASPROCESSED, OnCalllogMarkasprocessed)
+ ON_WM_SIZE()
+ ON_WM_GETMINMAXINFO()
+ ON_BN_CLICKED(IDC_AWAY, OnAway)
+ ON_CBN_SELENDOK(IDC_ONCALL, OnSelendokOncall)
+ ON_CBN_SELENDOK(IDC_ONCALLAWAY, OnSelendokOncallaway)
+ ON_COMMAND(ID_TRAY_AWAY, OnTrayAway)
+ ON_WM_TIMER()
+ ON_WM_QUERYENDSESSION()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42Dlg message handlers
+
+BOOL CT42Dlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Add "About..." menu item to system menu.
+
+ // IDM_ABOUTBOX must be in the system command range.
+ ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+ ASSERT(IDM_ABOUTBOX < 0xF000);
+
+ CMenu* pSysMenu = GetSystemMenu(FALSE);
+ CString strAboutMenu;
+ strAboutMenu.LoadString(IDS_ABOUTBOX);
+ if (!strAboutMenu.IsEmpty())
+ {
+ pSysMenu->AppendMenu(MF_SEPARATOR);
+ pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+ }
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+CT42App* app = (CT42App*)AfxGetApp();
+{
+int x = -1,y = -1,cx = -1,cy = -1;
+ x = app->GetProfileInt("T42MainWindow","X",x);
+ y = app->GetProfileInt("T42MainWindow","Y",y);
+ cx = app->GetProfileInt("T42MainWindow","Width",cx);
+ cy = app->GetProfileInt("T42MainWindow","Height",cy);
+ if(cx>0 && cy>0)
+ SetWindowPos(NULL,x,y,cx,cy,SWP_NOACTIVATE|SWP_NOZORDER);
+}
+
+ ::SetForegroundWindow(m_hExFW);
+
+ m_PreviewCtl.ModifyStyle(0,WS_VSCROLL);
+ m_PreviewCtl.SetOptions(ECOOP_SET,ECO_AUTOWORDSELECTION|
+ ECO_AUTOVSCROLL|ECO_AUTOHSCROLL|ECO_READONLY|ECO_SELECTIONBAR);
+ m_PreviewCtl.SetReadOnly(TRUE);
+ m_PreviewCtl.SetTargetDevice(NULL,0);
+ m_PreviewCtl.SetBackgroundColor(FALSE,((CT42App*)AfxGetApp())->m_crT42RemoteBG);
+
+ m_CallsCtl.SetBkColor(RGB(0,192,0));
+ m_CallsCtl.SetTextColor(RGB(255,255,0));
+ m_CallsCtl.SetTextBkColor(RGB(0,192,0));
+ m_Images.Create(16,16,TRUE,2,1);
+ m_iNew = m_Images.Add(AfxGetApp()->LoadIcon(IDI_T42CALLNEW));
+ m_iProcessed = m_Images.Add(AfxGetApp()->LoadIcon(IDI_T42CALLPROCESSED));
+ ASSERT( m_iNew>=0 && m_iProcessed>=0);
+ m_CallsCtl.SetImageList(&m_Images,LVSIL_NORMAL);
+ m_CallsCtl.SetImageList(&m_Images,LVSIL_SMALL);
+ m_CallsCtl.SetImageList(&m_Images,LVSIL_STATE);
+ InitCalls();
+
+CRect wrci, wrco;
+ GetWindowRect(&wrco);
+ GetClientRect(&wrci);
+ // Pull out margins
+CRect crc;
+ m_CallsCtl.GetWindowRect(crc); ScreenToClient(crc);
+ m_marginX = crc.left;
+CRect trc;
+ m_TeaCtl.GetWindowRect(trc); ScreenToClient(trc);
+ m_marginY = trc.top;
+CRect prc;
+ m_PreviewCtl.GetWindowRect(prc); ScreenToClient(prc);
+ m_gapY = prc.top-crc.bottom;
+
+ RecalcLayout();
+ SetColumnWidths();
+
+ // Calc minimum size
+CRect arc;
+ m_AwayCtl.GetWindowRect(arc); ScreenToClient(arc);
+ m_sizeMin.cx = arc.right+m_marginX*2+trc.Width()+wrco.Width()-wrci.Width();
+ m_sizeMin.cy = crc.top+m_marginY+m_gapY+40*2+wrco.Height()-wrci.Height();
+
+ SetTimer(timerMinutes,60000,NULL);
+
+ m_daemonSocket = socket(AF_INET,SOCK_DGRAM,0);
+ if(m_daemonSocket == INVALID_SOCKET){
+ TRACE0("Failed to initialize daemon\n");
+ return TRUE;
+ }
+sockaddr_in da;
+ da.sin_family = AF_INET;
+ da.sin_port = htons(app->m_T42TalkPort);
+ da.sin_addr.s_addr = INADDR_ANY;
+ if(bind(m_daemonSocket,(sockaddr*)&da,sizeof(da))){
+ AfxMessageBox(IDS_DAEMON_FAIL,MB_OK|MB_ICONSTOP);
+ TRACE0("Failed to bind daemon socket\n");
+ return TRUE;
+ }
+ if(WSAAsyncSelect(m_daemonSocket,m_hWnd,WM_DAEMON,FD_READ)){
+ AfxMessageBox(IDS_DAEMON_FAIL,MB_OK|MB_ICONSTOP);
+ TRACE0("AsyncSelect failed on daemon socket\n");
+ return TRUE;
+ }
+
+ return TRUE; // return TRUE unless you set the focus to a control
+}
+
+void CT42Dlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+ if ((nID & 0xFFF0) == IDM_ABOUTBOX){
+ CAboutDlg dlgAbout;
+ dlgAbout.DoModal();
+ }else{
+ if(nID==SC_SCREENSAVE){
+ TRACE0("SCRS\n");
+ }else if(nID==SC_MONITORPOWER){
+ TRACE0("MP\n");
+ }else
+ TRACE1("SYSCOM: 0x%04X\n",nID);
+ CDialog::OnSysCommand(nID, lParam);
+ }
+}
+
+void CT42Dlg::OnDestroy()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+CDocTemplate* pTemplate = app->m_pTemplate;
+ pTemplate->CloseAllDocuments(FALSE);
+CRect rc;
+ GetWindowRect(rc);
+ app->WriteProfileInt("T42MainWindow","X",rc.left);
+ app->WriteProfileInt("T42MainWindow","Y",rc.top);
+ app->WriteProfileInt("T42MainWindow","Width",rc.Width());
+ app->WriteProfileInt("T42MainWindow","Height",rc.Height());
+
+NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize=sizeof(nid);
+ nid.hWnd=m_hWnd;
+ nid.uID=IDC_TRAYICON;
+ nid.uFlags=0;
+ VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid));
+
+ WinHelp(0L, HELP_QUIT);
+ CDialog::OnDestroy();
+}
+
+// If you add a minimize button to your dialog, you will need the code below
+// to draw the icon. For MFC applications using the document/view model,
+// this is automatically done for you by the framework.
+
+void CT42Dlg::OnPaint()
+{
+ if (IsIconic())
+ {
+ CPaintDC dc(this); // device context for painting
+
+ SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else
+ {
+ CPaintDC pDC(this);
+ CDC bmpDC;
+ bmpDC.CreateCompatibleDC(&pDC);
+ bmpDC.SelectObject(&m_bmpBack);
+ CRect rc;
+ GetClientRect(&rc);
+ for(int x=-m_bitmapBack.bmWidth*2/4;x<rc.Width();x+=m_bitmapBack.bmWidth)
+ for(int y=-m_bitmapBack.bmHeight*2/4;y<rc.Height();y+=m_bitmapBack.bmHeight)
+ pDC.BitBlt(x,y,m_bitmapBack.bmWidth,m_bitmapBack.bmHeight,&bmpDC,0,0,SRCCOPY);
+ bmpDC.DeleteDC();
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this to obtain the cursor to display while the user drags
+// the minimized window.
+HCURSOR CT42Dlg::OnQueryDragIcon()
+{
+ return (HCURSOR) m_hIcon;
+}
+
+void CT42Dlg::OnTalk()
+{
+CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate;
+T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile(NULL);
+ ASSERT_KINDOF(T42Document,pDoc);
+ pDoc->Talk();
+}
+
+LRESULT CT42Dlg::OnDaemon(WPARAM wP,LPARAM lP)
+{
+ if(WSAGETSELECTERROR(lP)){
+ TRACE1("Error on daemon socket: %ld\n", WSAGETSELECTERROR(lP));
+ return -1;
+ }
+ ASSERT(WSAGETSELECTEVENT(lP)&FD_READ);
+TalkCtlMessage rq;
+ if(recv(m_daemonSocket,(char*)&rq,sizeof(rq),0)!=sizeof(rq)){
+ TRACE("Bad packet size on daemon socket\n");
+ return -1;
+ }
+TalkCtlResponse rp;
+ TRACE3("*DAEMON-REQUEST*\nV: %d, T: %d, ID: %ld\n",
+ (int)rq.m_Version, (int)rq.m_Type, ntohl(rq.m_ID)
+ );
+ TRACE2("ADDR: %s:%d\n",
+ inet_ntoa(((sockaddr_in*)&rq.m_Addr)->sin_addr),
+ ntohs(((sockaddr_in*)&rq.m_Addr)->sin_port)
+ );
+ TRACE2("CTL ADDR: %s:%d\n",
+ inet_ntoa(((sockaddr_in*)&rq.m_ctlAddr)->sin_addr),
+ ntohs(((sockaddr_in*)&rq.m_ctlAddr)->sin_port)
+ );
+ TRACE3("PID: %ld, LU: %s, RU: %s\n",
+ rq.m_PID,rq.m_LName,rq.m_RName
+ );
+ TRACE1("TTY: %s\n---\n",rq.m_RTTY);
+
+ rp.m_Version = talkCtlVersion;
+ rp.m_Type = rq.m_Type;
+ rp.m_ID = htonl(0);
+ rp.m_Answer = talkCtlReserved;
+sockaddr_in a;
+ memmove(&a,&rq.m_ctlAddr,sizeof(a));
+ a.sin_family = ntohs(a.sin_family);
+ do{
+ if(rq.m_Version!=talkCtlVersion){
+ rp.m_Answer = talkCtlBadVersion;
+ break;
+ }
+ if(rq.m_Addr.sa_family!=htons(AF_INET)){
+ rp.m_Answer = talkCtlBadAddr;
+ break;
+ }
+ if(rq.m_ctlAddr.sa_family!=htons(AF_INET)){
+ rp.m_Answer = talkCtlBadCtlAddr;
+ break;
+ }
+ switch(rq.m_Type){
+ case talkCtlReqAnnounce:
+ {
+ CTime ct = CTime::GetCurrentTime();
+ POSITION p = m_talks.GetHeadPosition();
+ BOOL bFound = FALSE;
+ while(p){
+ POSITION dp = p;
+ CTTable& t = m_talks.GetNext(p);
+ if((ct-t.m_Time)>m_talkLifetime){
+ TRACE0("Removing Expired request\n");
+ m_talks.RemoveAt(dp);
+ }else if(t==rq){
+ t.m_Time = ct;
+ rp.m_ID = t.m_RQ.m_ID;
+ bFound = TRUE;
+ break;
+ }
+ }
+ if(bFound){
+ // ** handle re-announces
+ rp.m_Answer = talkCtlSuccess;
+ break;
+ }
+ UINT nAction = m_bAway?m_onCallAway:m_onCall;
+ T42AnnounceDlg ad(rq);
+ CT42App* app = (CT42App*)AfxGetApp();
+ if(
+ nAction==IDC_SECRETARY
+ && app->m_T42SWinLimit
+ && app->m_T42LinesBusy>=app->m_T42SWinLimit
+ )
+ nAction = IDC_NOTHERE; // ??
+ if(nAction!=IDC_SECRETARY && nAction!=IDC_NOTHERE
+ && nAction!=IDC_REFUSE && nAction!=IDCANCEL
+ ){
+ CTTable t;
+ memmove(&t.m_RQ,&rq,sizeof(t.m_RQ));
+ t.m_Time = ct;
+ t.m_RQ.m_ID = rp.m_ID = htonl(m_trackTalkID++);
+ m_talks.AddHead(t);
+ rp.m_Answer = talkCtlSuccess;
+ if(sendto(m_daemonSocket,(char*)&rp,sizeof(rp),0,(sockaddr*)&a,sizeof(a))!=sizeof(rp)){
+ TRACE0("Failed to send daemon response\n");
+ return -1;
+ }
+ HWND hFW = ::GetForegroundWindow();
+ nAction = ad.DoModal();
+ ::SetForegroundWindow(hFW);
+ }else{
+ if(nAction==IDC_NOTHERE || nAction==IDC_REFUSE){
+ rp.m_Answer=(nAction==IDC_NOTHERE)?talkCtlNotHere:talkCtlPermissionDenied;
+ break;
+ }
+ CTTable t;
+ memmove(&t.m_RQ,&rq,sizeof(t.m_RQ));
+ t.m_Time = ct;
+ t.m_RQ.m_ID = rp.m_ID = htonl(m_trackTalkID++);
+ m_talks.AddHead(t);
+ rp.m_Answer = talkCtlSuccess;
+ if(sendto(m_daemonSocket,(char*)&rp,sizeof(rp),0,(sockaddr*)&a,sizeof(a))!=sizeof(rp)){
+ TRACE0("Failed to send daemon response\n");
+ return -1;
+ }
+ }
+ rp.m_Answer=talkCtlReserved;
+ switch(nAction){
+ case IDOK:
+ {
+ CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate;
+ T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile(NULL);
+ ASSERT_KINDOF(T42Document,pDoc);
+ pDoc->Talk(ad.m_Callee,ad.m_ipCaller,NULL);
+ }
+ break;
+ case IDC_SECRETARY:
+ {
+ HWND hFW = ::GetForegroundWindow();
+ CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate;
+ T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile("hidden");
+ ASSERT_KINDOF(T42Document,pDoc);
+ pDoc->AttachRobot(new CT42Secretary);
+ pDoc->Talk(ad.m_Callee,ad.m_ipCaller,NULL);
+ ::SetForegroundWindow(hFW);
+ }
+ break;
+ case IDCANCEL:
+ break;
+ }
+ }
+ break;
+ case talkCtlReqLeaveInvite:
+ {
+ CTime ct = CTime::GetCurrentTime();
+ POSITION p = m_talks.GetHeadPosition();
+ while(p){
+ POSITION dp = p;
+ CTTable& t = m_talks.GetNext(p);
+ if((ct-t.m_Time)>m_talkLifetime){
+ TRACE0("Removing Expired request\n");
+ m_talks.RemoveAt(dp);
+ }else if(t==rq){
+ t.m_Time = ct;
+ rp.m_ID = rq.m_ID;
+ rp.m_Answer = talkCtlSuccess;
+ break;
+ }
+ }
+ if(rp.m_Answer!=talkCtlSuccess){
+ CTTable t;
+ memmove(&t.m_RQ,&rq,sizeof(t.m_RQ));
+ t.m_Time = ct;
+ t.m_RQ.m_ID = rp.m_ID = htonl(m_trackTalkID++);
+ m_talks.AddHead(t);
+ rp.m_Answer = talkCtlSuccess;
+ }
+ }
+ break;
+ case talkCtlReqLookUp:
+ {
+ CTime ct = CTime::GetCurrentTime();
+ POSITION p = m_talks.GetHeadPosition();
+ while(p){
+ POSITION dp = p;
+ CTTable& t = m_talks.GetNext(p);
+ if((ct-t.m_Time)>m_talkLifetime){
+ TRACE0("Removing Expired request\n");
+ m_talks.RemoveAt(dp);
+ }else if(t.Match(rq)){
+ rp.m_ID = t.m_RQ.m_ID;
+ memmove(&rp.m_Addr,&t.m_RQ.m_Addr,sizeof(rp.m_Addr));
+ rp.m_Answer = talkCtlSuccess;
+ break;
+ }
+ }
+ if(rp.m_Answer!=talkCtlSuccess)
+ rp.m_Answer = talkCtlNotHere;
+ }
+ break;
+ case talkCtlReqDelete:
+ {
+ CTime ct = CTime::GetCurrentTime();
+ POSITION p = m_talks.GetHeadPosition();
+ while(p){
+ POSITION dp = p;
+ CTTable& t = m_talks.GetNext(p);
+ if((ct-t.m_Time)>m_talkLifetime){
+ TRACE0("Removing Expired request\n");
+ m_talks.RemoveAt(dp);
+ }else if(t.m_RQ.m_ID == rq.m_ID){
+ m_talks.RemoveAt(dp);
+ rp.m_Answer=talkCtlSuccess;
+ break;
+ }
+ }
+ if(rp.m_Answer!=talkCtlSuccess)
+ rp.m_Answer = talkCtlNotHere;
+ break;
+ }
+ break;
+ default:
+ TRACE0("Unknown request type\n");
+ rp.m_Answer=talkCtlUnknownRequest;
+ break;
+ }
+ }while(FALSE);
+ if(rp.m_Answer==talkCtlReserved || rp.m_Answer==talkCtlBadCtlAddr)
+ return -1;
+ if(sendto(m_daemonSocket,(char*)&rp,sizeof(rp),0,(sockaddr*)&a,sizeof(a))!=sizeof(rp)){
+ TRACE0("Failed to send daemon response\n");
+ return -1;
+ }
+ return 0;
+}
+
+int CT42Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CDialog::OnCreate(lpCreateStruct) == -1)
+ return -1;
+CRichEditCtrl tmp;
+ tmp.Create(WS_CHILD,CRect(0,0,0,0),this,0);
+
+NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = m_hWnd;
+ nid.uID = IDC_TRAYICON;
+ nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
+ nid.uCallbackMessage=WM_TRAYICON;
+ nid.hIcon = m_hIcon;
+ // ***
+ strcpy(nid.szTip,"Tea For Two");
+ VERIFY(Shell_NotifyIcon(NIM_ADD,&nid));
+
+ return 0;
+}
+
+LRESULT CT42Dlg::OnTrayIcon(WPARAM wP,LPARAM lP)
+{
+ ASSERT(wP==IDC_TRAYICON);
+ switch(lP){
+ case WM_LBUTTONDOWN:
+ ToggleVisibility();
+ break;
+ case WM_RBUTTONDOWN:
+ {
+ CMenu popups;
+ VERIFY(popups.LoadMenu(IDM_POPUPS));
+ CMenu* popUp = popups.GetSubMenu(0);
+ ASSERT(popUp);
+ CPoint pt;
+ VERIFY(::GetCursorPos(&pt));
+ SetForegroundWindow();
+ popUp->CheckMenuItem(ID_TRAY_SHOWMAINWINDOW,MF_BYCOMMAND|(IsWindowVisible()?MF_CHECKED:MF_UNCHECKED));
+ popUp->CheckMenuItem(ID_TRAY_AWAY,MF_BYCOMMAND|(m_bAway?MF_CHECKED:MF_UNCHECKED));
+ popUp->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
+ pt.x,pt.y,this);
+ SendMessage(WM_NULL);
+ }
+ break;
+ }
+ return 0;
+}
+
+void CT42Dlg::ToggleVisibility()
+{
+ if(IsWindowVisible()){
+ m_bShown=FALSE;
+ ShowWindow(SW_HIDE);
+ CWnd* pWnd = GetNextWindow();
+ if(pWnd){
+ pWnd->SetForegroundWindow();
+ pWnd->SetFocus();
+ }
+ }else{
+ m_bShown=TRUE;
+ ShowWindow(SW_SHOW);
+ SetForegroundWindow();
+ SetFocus();
+ }
+}
+
+void CT42Dlg::OnCancel()
+{
+ ToggleVisibility();
+}
+
+
+void CT42Dlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
+{
+ CDialog::OnWindowPosChanging(lpwndpos);
+
+ if(m_bExiting)
+ return;
+ if(m_bShown){
+ lpwndpos->flags&=~SWP_HIDEWINDOW;
+ lpwndpos->flags|=SWP_SHOWWINDOW;
+ }else{
+ lpwndpos->flags&=~SWP_SHOWWINDOW;
+ lpwndpos->flags|=SWP_HIDEWINDOW;
+ }
+}
+
+void CT42Dlg::OnOK()
+{
+ m_bExiting = TRUE;
+ CDialog::OnOK();
+}
+
+void CT42Dlg::OnTrayExit()
+{
+ OnOK();
+}
+
+void CT42Dlg::OnTrayOptions()
+{
+ OnOptions();
+}
+
+void CT42Dlg::OnTrayShowmainwindow()
+{
+ ToggleVisibility();
+}
+
+void CT42Dlg::OnTrayT42()
+{
+ OnTalk();
+}
+
+void CT42Dlg::OnOptions()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ app->Options(this);
+}
+
+void CT42Dlg::InitCalls()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ m_CallsCtl.InsertColumn(0,"Time",LVCFMT_LEFT,-1,subitemTime);
+ m_CallsCtl.InsertColumn(1,"Caller",LVCFMT_LEFT,-1,subitemCaller);
+ m_CallsCtl.InsertColumn(2,"Callee",LVCFMT_LEFT,-1,subitemCallee);
+LONG calls = app->GetT42Calls();
+ if(calls>0){
+ m_CallsCtl.SetItemCount(calls);
+ for(LONG tmp=0;tmp<calls;tmp++){
+ m_CallsCtl.InsertItem(
+ LVIF_TEXT,
+ tmp,
+ LPSTR_TEXTCALLBACK,
+ 0,0, // state,statemask
+ I_IMAGECALLBACK,
+ 0 // lParam
+ );
+ }
+ }
+ SetColumnWidths();
+}
+
+void CT42Dlg::OnGetdispinfoCalls(NMHDR* pNMHDR, LRESULT* pResult)
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
+int iItem = pDispInfo->item.iItem;
+CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(iItem,entry));
+CString tmp;
+ switch(pDispInfo->item.iSubItem){
+ case subitemTime:
+ tmp = entry.m_Time.Format(IDS_FORMAT_CALLTIME);
+ if(entry.m_Status==CT42CallLogEntry::statusProcessed)
+ pDispInfo->item.iImage = m_iProcessed;
+ else
+ pDispInfo->item.iImage = m_iNew;
+ break;
+ case subitemCaller:
+ tmp = entry.m_Caller;
+ break;
+ case subitemCallee:
+ tmp = entry.m_Callee;
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+ if(tmp.GetLength()>=pDispInfo->item.cchTextMax)
+ tmp = tmp.Left(pDispInfo->item.cchTextMax-4)+"..";
+ strcpy(pDispInfo->item.pszText,tmp);
+ pDispInfo->item.mask|=LVIF_IMAGE;
+ pDispInfo->item.mask|=LVIF_TEXT;
+
+ *pResult = 0;
+}
+
+void CT42Dlg::OnAddT42Call()
+{
+ m_CallsCtl.InsertItem(
+ LVIF_TEXT,
+ m_CallsCtl.GetItemCount(),
+ LPSTR_TEXTCALLBACK,
+ 0,0, // state,statemask
+ I_IMAGECALLBACK,
+ 0 // lParam
+ );
+ m_CallsCtl.RedrawItems(0,m_CallsCtl.GetItemCount());
+ m_CallsCtl.Invalidate();
+ PostMessage(WM_UPDATEPREVIEW,(WPARAM)-1);
+ if(!IsWindowVisible()){
+ m_newCalls++;
+ SetTheIcon(m_hIconFull);
+ }
+}
+
+void CT42Dlg::OnDelT42Call()
+{
+ m_CallsCtl.DeleteItem(
+ m_CallsCtl.GetItemCount()-1
+ );
+ m_CallsCtl.RedrawItems(0,m_CallsCtl.GetItemCount());
+ m_CallsCtl.Invalidate();
+ PostMessage(WM_UPDATEPREVIEW,(WPARAM)-1);
+}
+
+void CT42Dlg::SetColumnWidths()
+{
+CTime ct = CTime::GetCurrentTime();
+CString t = ct.Format(IDS_FORMAT_CALLTIME);
+CRect rc;
+ m_CallsCtl.GetClientRect(rc);
+INT tw = m_CallsCtl.GetStringWidth(t)+40;
+INT cew = m_CallsCtl.GetStringWidth("wwwwwwww");
+INT crw = rc.Width()-(tw+cew);
+ m_CallsCtl.SetColumnWidth(subitemTime,tw);
+ m_CallsCtl.SetColumnWidth(subitemCaller,crw);
+ m_CallsCtl.SetColumnWidth(subitemCallee,cew);
+}
+
+void CT42Dlg::OnItemchangedCalls(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
+
+ if(
+ pNMListView->uChanged&LVIF_STATE
+ && pNMListView->uNewState&LVIS_FOCUSED
+ && !(pNMListView->uOldState&LVIS_FOCUSED)
+ ){
+ PostMessage(WM_UPDATEPREVIEW,pNMListView->iItem);
+ }
+ *pResult = 0;
+}
+
+DWORD CALLBACK CT42Dlg::ESOUTProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb)
+{
+CString* str = (CString*)dwCookie;
+ if(cb>str->GetLength())
+ cb = str->GetLength();
+ if(!cb){
+ (*pcb)=0;
+ return 0;
+ }
+ memmove(pbBuff,(LPCTSTR)*str,cb);
+ (*str) = str->Mid(cb);
+ (*pcb)=cb;
+ return 0;
+}
+
+void CT42Dlg::OnRclickCalls(NMHDR* pNMHDR, LRESULT* pResult)
+{
+CPoint pt;
+ VERIFY(GetCursorPos(&pt));
+CMenu popups;
+ VERIFY(popups.LoadMenu(IDM_POPUPS));
+CMenu* popup = popups.GetSubMenu(1);
+ ASSERT(popup);
+BOOL bYes = (
+ m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_FOCUSED)>=0
+ || m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_SELECTED)>=0
+ );
+ popup->EnableMenuItem(ID_CALLLOG_CALLBACK,MF_BYCOMMAND|(
+ bYes?MF_ENABLED:MF_GRAYED
+ ));
+ popup->EnableMenuItem(ID_CALLLOG_DELETE,MF_BYCOMMAND|(
+ bYes?MF_ENABLED:MF_GRAYED
+ ));
+ popup->EnableMenuItem(ID_CALLLOG_SAVETOFILE,MF_BYCOMMAND|(
+ bYes?MF_ENABLED:MF_GRAYED
+ ));
+ popup->EnableMenuItem(ID_CALLLOG_MARKASNEW,MF_BYCOMMAND|(
+ bYes?MF_ENABLED:MF_GRAYED
+ ));
+ popup->EnableMenuItem(ID_CALLLOG_MARKASPROCESSED,MF_BYCOMMAND|(
+ bYes?MF_ENABLED:MF_GRAYED
+ ));
+ popup->EnableMenuItem(ID_CALLLOG_EMPTYLOG,MF_BYCOMMAND|(
+ (m_CallsCtl.GetItemCount())?MF_ENABLED:MF_GRAYED
+ ));
+ popup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_LEFTBUTTON,
+ pt.x,pt.y,this);
+ *pResult = 0;
+}
+
+void CT42Dlg::OnCalllogCallback()
+{
+int item = m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_FOCUSED);
+ if(item<0)
+ return;
+CT42App* app = (CT42App*)AfxGetApp();
+CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(item,entry));
+CDocTemplate* pTemplate = app->m_pTemplate;
+T42Document* pDoc = (T42Document*)pTemplate->OpenDocumentFile(NULL);
+ ASSERT_KINDOF(T42Document,pDoc);
+ pDoc->Talk(entry.m_Callee,entry.m_Caller,NULL);
+ entry.m_Status=CT42CallLogEntry::statusProcessed;
+ VERIFY(app->UpdateT42Call(entry));
+ m_CallsCtl.Update(item);
+}
+
+void CT42Dlg::OnCalllogDelete()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+int ii = m_CallsCtl.GetItemCount();
+ if(ii<=0)
+ return;
+Klever::CBitSet bs(ii);
+ for(int i=0;i<ii;i++)
+ if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED))
+ bs.BitSet(i);
+ for(i = (ii-1);i>=0;i--){
+ if(!bs.IsSet(i))
+ continue;
+ CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(i,entry));
+ VERIFY(app->DelT42Call(entry.m_Time));
+ }
+}
+
+void CT42Dlg::OnCalllogSavetofile()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+CT42CallLogEntry entry;
+CString filter;
+ VERIFY(filter.LoadString(IDS_FILTER_RTF));
+CFileDialog fd(FALSE,".rtf",NULL,
+ OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER|
+ OFN_LONGNAMES|OFN_NOREADONLYRETURN|OFN_PATHMUSTEXIST,
+ filter,this
+ );
+ if(fd.DoModal()==IDOK){
+ int ii = m_CallsCtl.GetItemCount();
+ if(ii<=0)
+ return;
+ Klever::CBitSet bs(ii);
+ for(int i=0;i<ii;i++)
+ if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED))
+ bs.BitSet(i);
+ try{
+ CStdioFile f(fd.GetPathName(),
+ CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite|
+ CFile::typeText);
+ f.WriteString("{\\rtf1\\ansi\n");
+ for(i = (ii-1);i>=0;i--){
+ if(!bs.IsSet(i))
+ continue;
+ CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(i,entry));
+ CString tmp;
+ tmp.Format(IDS_FORMAT_T42CALLHEADER,
+ entry.m_Time.Format(IDS_FORMAT_CALLTIMELONG),
+ entry.m_Caller, entry.m_Callee,
+ entry.m_Duration.Format(IDS_FORMAT_CALLDURATION)
+ );
+ f.WriteString(tmp);
+ f.WriteString(entry.m_Message);
+ }
+ f.WriteString("\n}\n");
+ }catch(CException* e){
+ TRACE0("Save exc\n");
+ e->Delete();
+ }
+ }
+}
+
+void CT42Dlg::OnCalllogEmptylog()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+int ii = m_CallsCtl.GetItemCount();
+ if(ii<=0)
+ return;
+ for(int i = (ii-1);i>=0;i--){
+ CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(i,entry));
+ VERIFY(app->DelT42Call(entry.m_Time));
+ }
+}
+
+void CT42Dlg::OnDeleteitemCalls(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
+ PostMessage(WM_UPDATEPREVIEW,(WPARAM)-1);
+ *pResult = 0;
+}
+
+LRESULT CT42Dlg::OnUpdatePreview(WPARAM wP,LPARAM)
+{
+int iItem = (int)wP;
+ if(iItem<0)
+ iItem = m_CallsCtl.GetNextItem(-1,LVNI_ALL|LVNI_FOCUSED);
+CT42App* app = (CT42App*)AfxGetApp();
+CT42CallLogEntry entry;
+ if(iItem<0 ||!app->GetT42Call(iItem,entry)){
+ m_PreviewCtl.SetWindowText("");
+ return 0;
+ }
+EDITSTREAM es;
+ memset(&es,0,sizeof(es));
+ es.dwCookie = (DWORD)&entry.m_Message;
+ es.pfnCallback = ESOUTProc;
+ m_PreviewCtl.StreamIn(SF_RTF,es);
+ return 0;
+}
+
+void CT42Dlg::OnKeydownCalls(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
+
+ switch(pLVKeyDow->wVKey){
+ case 'R':
+ if(GetKeyState(VK_CONTROL)&0x8000)
+ OnCalllogCallback();
+ break;
+ case VK_DELETE:
+ OnCalllogDelete();
+ break;
+ case 'D':
+ if(GetKeyState(VK_CONTROL)&0x8000)
+ OnCalllogDelete();
+ break;
+ }
+ *pResult = 0;
+}
+
+BOOL CT42Dlg::PreCreateWindow(CREATESTRUCT& cs)
+{
+ m_hExFW = ::GetForegroundWindow();
+ return CDialog::PreCreateWindow(cs);
+}
+
+void CT42Dlg::SetTheIcon(HICON hIcon)
+{
+ m_hIcon = hIcon;
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = m_hWnd;
+ nid.uID = IDC_TRAYICON;
+ nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
+ nid.uCallbackMessage=WM_TRAYICON;
+ nid.hIcon = hIcon;
+ if(m_newCalls)
+ _snprintf(nid.szTip,sizeof(nid.szTip)-1,"%d new calls waiting",m_newCalls);
+ else
+ strcpy(nid.szTip,"Tea For Two");
+ VERIFY(Shell_NotifyIcon(NIM_MODIFY,&nid));
+}
+
+void CT42Dlg::OnShowWindow(BOOL bShow, UINT nStatus)
+{
+ CDialog::OnShowWindow(bShow, nStatus);
+ if(bShow){
+ m_newCalls=0;
+ SetTheIcon(m_hIconEmpty);
+ }
+}
+
+void CT42Dlg::OnCalllogMarkasnew()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+int ii = m_CallsCtl.GetItemCount();
+ if(ii<=0)
+ return;
+Klever::CBitSet bs(ii);
+ for(int i=0;i<ii;i++)
+ if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED))
+ bs.BitSet(i);
+int f = -1,t = -1;
+ for(i = 0;i<ii;i++){
+ if(!bs.IsSet(i))
+ continue;
+ CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(i,entry));
+ if(entry.m_Status==CT42CallLogEntry::statusProcessed){
+ entry.m_Status=CT42CallLogEntry::statusOk;
+ VERIFY(app->UpdateT42Call(entry));
+ if(f<0)
+ f=i;
+ if(t<i)
+ t=i;
+ }
+ }
+ if(f<0 || t<0)
+ return;
+ m_CallsCtl.RedrawItems(f,t);
+ m_CallsCtl.Invalidate();
+}
+
+void CT42Dlg::OnCalllogMarkasprocessed()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+int ii = m_CallsCtl.GetItemCount();
+ if(ii<=0)
+ return;
+Klever::CBitSet bs(ii);
+ for(int i=0;i<ii;i++)
+ if(m_CallsCtl.GetItemState(i,LVIS_FOCUSED|LVIS_SELECTED))
+ bs.BitSet(i);
+int f = -1,t = -1;
+ for(i = 0;i<ii;i++){
+ if(!bs.IsSet(i))
+ continue;
+ CT42CallLogEntry entry;
+ VERIFY(app->GetT42Call(i,entry));
+ if(entry.m_Status!=CT42CallLogEntry::statusProcessed){
+ entry.m_Status=CT42CallLogEntry::statusProcessed;
+ VERIFY(app->UpdateT42Call(entry));
+ if(f<0)
+ f=i;
+ if(t<i)
+ t=i;
+ }
+ }
+ if(f<0 || t<0)
+ return;
+ m_CallsCtl.RedrawItems(f,t);
+ m_CallsCtl.Invalidate();
+}
+
+void CT42Dlg::RecalcLayout()
+{
+CRect crc;
+ GetClientRect(&crc);
+CRect rcCalls;
+ m_CallsCtl.GetWindowRect(&rcCalls);
+ ScreenToClient(rcCalls);
+ // Calculate windows height.
+UINT wHeight = (crc.Height()-rcCalls.top-m_marginY-m_gapY)/2;
+UINT wWidth = crc.Width()-(2*m_marginX);
+ // Position windows
+ m_CallsCtl.SetWindowPos(
+ NULL,
+ m_marginX,rcCalls.top-crc.top, wWidth,wHeight,
+ SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER
+ );
+ m_PreviewCtl.SetWindowPos(
+ NULL,
+ m_marginX,rcCalls.top-crc.top+wHeight+m_gapY, wWidth,wHeight,
+ SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER
+ );
+
+CRect brc;
+ m_TeaCtl.GetWindowRect(brc); ScreenToClient(brc);
+UINT bX = crc.Width()-m_marginX-brc.Width();
+ m_TeaCtl.SetWindowPos(NULL,bX,brc.top, 0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
+ m_OptionsCtl.GetWindowRect(brc); ScreenToClient(brc);
+ m_OptionsCtl.SetWindowPos(NULL,bX,brc.top,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
+ m_ExitCtl.GetWindowRect(brc); ScreenToClient(brc);
+ m_ExitCtl.SetWindowPos(NULL,bX,brc.top,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
+ m_HelpCtl.GetWindowRect(brc); ScreenToClient(brc);
+ m_HelpCtl.SetWindowPos(NULL,bX,brc.top,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS);
+}
+
+void CT42Dlg::OnSize(UINT nType, int cx, int cy)
+{
+ CDialog::OnSize(nType, cx, cy);
+
+ if(m_marginX && m_marginY && m_gapY){
+ RecalcLayout();
+ SetColumnWidths();
+ }
+
+}
+
+void CT42Dlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
+{
+ if(m_sizeMin.cx && m_sizeMin.cy){
+ lpMMI->ptMinTrackSize.x = m_sizeMin.cx;
+ lpMMI->ptMinTrackSize.y = m_sizeMin.cy;
+ }
+
+ CDialog::OnGetMinMaxInfo(lpMMI);
+}
+
+void CT42Dlg::SetOnCtl(UINT nAction,CComboBox& ctl)
+{
+int n = 0;
+ switch(nAction){
+ case IDC_SECRETARY: n = 1; break;
+ case IDC_NOTHERE: n = 2; break;
+ case IDC_REFUSE: n = 3; break;
+ case IDCANCEL: n = 4; break;
+ }
+ ctl.SetCurSel(n);
+}
+
+UINT CT42Dlg::GetOnCtl(CComboBox& ctl)
+{
+ switch(ctl.GetCurSel()){
+ case 1: return IDC_SECRETARY;
+ case 2: return IDC_NOTHERE;
+ case 3: return IDC_REFUSE;
+ case 4: return IDCANCEL;
+ }
+ return 0;
+}
+
+void CT42Dlg::OnAway()
+{
+ m_bAway = m_AwayCtl.GetCheck();
+}
+void CT42Dlg::OnSelendokOncall()
+{
+ m_onCall = GetOnCtl(m_OnCallCtl);
+}
+void CT42Dlg::OnSelendokOncallaway()
+{
+ m_onCallAway = GetOnCtl(m_OnCallAwayCtl);
+}
+
+void CT42Dlg::LoadSettings()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ m_onCall = app->GetProfileInt("Settings","T42OnCall",m_onCall);
+ m_onCallAway = app->GetProfileInt("Settings","T42OnCallAway",m_onCallAway);
+}
+
+void CT42Dlg::SaveSettings()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ app->WriteProfileInt("Settings","T42OnCall",m_onCall);
+ app->WriteProfileInt("Settings","T42OnCallAway",m_onCallAway);
+}
+
+void CT42Dlg::OnTrayAway()
+{
+ m_AwayCtl.SetCheck((m_bAway=!m_bAway)?1:0);
+}
+
+void CT42Dlg::OnTimer(UINT nIDEvent)
+{
+ if(nIDEvent==timerMinutes){
+ KillTimer(timerMinutes);
+ CDocTemplate* pTemplate = ((CT42App*)AfxGetApp())->m_pTemplate;
+ POSITION p = pTemplate->GetFirstDocPosition();
+ while(p){
+ T42Document* pDoc = (T42Document*)pTemplate->GetNextDoc(p);
+ pDoc->OnMinute();
+ }
+ SetTimer(timerMinutes,60000,NULL);
+ }
+
+ CDialog::OnTimer(nIDEvent);
+}
+
+BOOL CT42Dlg::OnQueryEndSession()
+{
+ if (!CDialog::OnQueryEndSession())
+ return FALSE;
+
+CT42App* app = (CT42App*)AfxGetApp();
+ app->SaveSettings();
+
+ return TRUE;
+}
diff --git a/T42Dlg.h b/T42Dlg.h
new file mode 100644
index 0000000..5f0b6d4
--- a/dev/null
+++ b/T42Dlg.h
@@ -0,0 +1,159 @@
+// T42Dlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CT42Dlg dialog
+
+class CTTable : public CObject {
+public:
+ TalkCtlMessage m_RQ;
+ CTime m_Time;
+
+ CTTable() {}
+ CTTable(CTTable& src) { Copy(src); }
+
+ void Copy(CTTable& src) {
+ memmove(&m_RQ,&src.m_RQ,sizeof(m_RQ));
+ m_Time = src.m_Time;
+ }
+
+ CTTable& operator=(CTTable& src) {
+ Copy(src);
+ return *this;
+ }
+
+ BOOL operator==(TalkCtlMessage& m) {
+ return (
+ strcmp(m_RQ.m_LName,m.m_LName)==0
+ && strcmp(m_RQ.m_RName,m.m_RName)==0
+ && m_RQ.m_Type == m.m_Type
+ && m_RQ.m_PID == m.m_PID
+ );
+ }
+
+ BOOL Match(TalkCtlMessage& m) {
+ return (
+ strcmp(m_RQ.m_LName,m.m_RName)==0
+ && strcmp(m_RQ.m_RName,m.m_LName)==0
+ && m_RQ.m_Type == talkCtlReqLeaveInvite
+ );
+ }
+};
+
+typedef CList<CTTable,CTTable&> CTRestaurant;
+
+class CT42Dlg : public CDialog
+{
+// Construction
+public:
+ ~CT42Dlg();
+ void SaveSettings();
+ void LoadSettings();
+ UINT GetOnCtl(CComboBox& ctl);
+ void SetOnCtl(UINT nAction,CComboBox& ctl);
+ UINT m_onCall;
+ UINT m_onCallAway;
+ BOOL m_bAway;
+ CSize m_sizeMin;
+ UINT m_gapY;
+ UINT m_marginY;
+ UINT m_marginX;
+ void RecalcLayout();
+ void SetTheIcon(HICON hIcon);
+ UINT m_newCalls;
+ HICON m_hIconEmpty;
+ HICON m_hIconFull;
+ HWND m_hExFW;
+ int m_iProcessed;
+ int m_iNew;
+ CImageList m_Images;
+ static DWORD CALLBACK ESOUTProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb);
+ void SetColumnWidths();
+ void OnDelT42Call();
+ void OnAddT42Call();
+ enum {
+ subitemTime=0,
+ subitemCaller, subitemCallee, subitemDuration,
+ subitemTTY
+ };
+ void InitCalls();
+ BOOL m_bShown;
+ BOOL m_bExiting;
+ void ToggleVisibility();
+ BITMAP m_bitmapBack;
+ CBitmap m_bmpBack;
+ DWORD m_trackTalkID;
+ CTimeSpan m_talkLifetime;
+ CTRestaurant m_talks;
+ CTRestaurant m_announcements;
+ SOCKET m_daemonSocket;
+ CT42Dlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CT42Dlg)
+ enum { IDD = IDD_T42_DIALOG };
+ CButton m_ExitCtl;
+ CButton m_TeaCtl;
+ CButton m_AwayCtl;
+ CButton m_HelpCtl;
+ CButton m_OptionsCtl;
+ CComboBox m_OnCallAwayCtl;
+ CComboBox m_OnCallCtl;
+ CListCtrl m_CallsCtl;
+ CRichEditCtrl m_PreviewCtl;
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CT42Dlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ HICON m_hIcon;
+
+ // Generated message map functions
+ //{{AFX_MSG(CT42Dlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+ afx_msg void OnDestroy();
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ afx_msg void OnTalk();
+ afx_msg LRESULT OnDaemon(WPARAM,LPARAM);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg LRESULT OnTrayIcon(WPARAM,LPARAM);
+ virtual void OnCancel();
+ afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);
+ virtual void OnOK();
+ afx_msg void OnTrayExit();
+ afx_msg void OnTrayOptions();
+ afx_msg void OnTrayShowmainwindow();
+ afx_msg void OnTrayT42();
+ afx_msg void OnOptions();
+ afx_msg void OnGetdispinfoCalls(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnItemchangedCalls(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnRclickCalls(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnCalllogCallback();
+ afx_msg void OnCalllogDelete();
+ afx_msg void OnCalllogSavetofile();
+ afx_msg void OnCalllogEmptylog();
+ afx_msg void OnDeleteitemCalls(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg LRESULT OnUpdatePreview(WPARAM,LPARAM);
+ afx_msg void OnKeydownCalls(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
+ afx_msg void OnCalllogMarkasnew();
+ afx_msg void OnCalllogMarkasprocessed();
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
+ afx_msg void OnAway();
+ afx_msg void OnSelendokOncall();
+ afx_msg void OnSelendokOncallaway();
+ afx_msg void OnTrayAway();
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg BOOL OnQueryEndSession();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/T42Document.cpp b/T42Document.cpp
new file mode 100644
index 0000000..3eeb427
--- a/dev/null
+++ b/T42Document.cpp
@@ -0,0 +1,181 @@
+// T42Document.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42Document.h"
+
+#include "T42View.h"
+#include "T42Frame.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Document
+
+IMPLEMENT_DYNCREATE(T42Document, CDocument)
+
+T42Document::T42Document()
+{
+ m_pView=NULL;
+ m_pRobot = NULL;
+ m_bHidden = FALSE;
+}
+
+BOOL T42Document::OnNewDocument()
+{
+ if (!CDocument::OnNewDocument())
+ return FALSE;
+ return TRUE;
+}
+
+T42Document::~T42Document()
+{
+ if(m_pRobot)
+ DetachRobot();
+}
+
+
+BEGIN_MESSAGE_MAP(T42Document, CDocument)
+ //{{AFX_MSG_MAP(T42Document)
+ ON_COMMAND(ID_WINDOW_SAVELAYOUT, OnWindowSavelayout)
+ ON_UPDATE_COMMAND_UI(ID_WINDOW_AUTOSAVELAYOUT, OnUpdateWindowAutosavelayout)
+ ON_COMMAND(ID_WINDOW_AUTOSAVELAYOUT, OnWindowAutosavelayout)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Document diagnostics
+
+#ifdef _DEBUG
+void T42Document::AssertValid() const
+{
+ CDocument::AssertValid();
+}
+
+void T42Document::Dump(CDumpContext& dc) const
+{
+ CDocument::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Document serialization
+
+void T42Document::Serialize(CArchive& ar)
+{
+ if (ar.IsStoring())
+ {
+ }
+ else
+ {
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Document commands
+
+void T42Document::Talk(LPCTSTR from,LPCTSTR to,LPCTSTR tty,BOOL bPrompt)
+{
+ ASSERT(m_pView);
+ ASSERT(m_pView->m_pFrame);
+ m_pView->m_pFrame->m_Target = to?to:"";
+ m_pView->m_pFrame->m_LocalUser = from?from:"";
+ m_pView->m_pFrame->m_TargetTTY = tty?tty:"";
+ if(bPrompt || !(to && from))
+ m_pView->m_pFrame->PostMessage(WM_COMMAND,MAKELONG(ID_TALK_REMOTEUSER,0),NULL);
+ else
+ m_pView->m_pFrame->PostMessage(WM_INITIATETALK);
+}
+
+void T42Document::OnChangedViewList()
+{
+ CDocument::OnChangedViewList();
+POSITION p = GetFirstViewPosition();
+ m_pView=NULL;
+ while(p){
+ CView* pView = GetNextView(p);
+ ASSERT_KINDOF(T42View,pView);
+ ASSERT(!m_pView);
+ m_pView=(T42View*)pView;
+ }
+}
+
+void T42Document::SaveLayout()
+{
+ ASSERT(m_pView);
+ m_pView->SaveLayout();
+ ASSERT(m_pView->m_pFrame);
+ m_pView->m_pFrame->SaveLayout();
+}
+
+void T42Document::OnWindowSavelayout()
+{
+ SaveLayout();
+}
+
+void T42Document::OnUpdateWindowAutosavelayout(CCmdUI* pCmdUI)
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ pCmdUI->SetCheck(app->m_bt42AutosaveLayout?1:0);
+}
+
+void T42Document::OnWindowAutosavelayout()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ app->m_bt42AutosaveLayout=!app->m_bt42AutosaveLayout;
+}
+
+void T42Document::AutosaveLayout()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ if(app->m_bt42AutosaveLayout)
+ SaveLayout();
+}
+
+BOOL T42Document::AttachRobot(CT42Robot* pRobot)
+{
+ if(m_pRobot)
+ DetachRobot();
+ m_pRobot = pRobot;
+ return m_pRobot->OnAttach(this);
+}
+
+BOOL T42Document::DetachRobot()
+{
+ ASSERT(m_pRobot);
+BOOL rv = m_pRobot->OnDetach();
+ m_pRobot=NULL;
+ return rv;
+}
+
+BOOL T42Document::SendOver(LPCTSTR str)
+{
+ // *** Or call T42View function?
+ for(LPCTSTR ptr=str;*ptr;ptr++){
+ m_pView->m_localCtl.PutCharacter(*ptr);
+ m_pView->m_pFrame->PostMessage(WM_TALKCHAR,0xFF&((WORD)*ptr));
+ }
+ return TRUE;
+}
+
+BOOL T42Document::OnOpenDocument(LPCTSTR lpszPathName)
+{
+// if (!CDocument::OnOpenDocument(lpszPathName))
+// return FALSE;
+
+ if(lpszPathName)
+ m_bHidden = TRUE;
+
+ return TRUE;
+}
+
+void T42Document::OnMinute()
+{
+ if(m_pRobot)
+ m_pRobot->OnMinute();
+}
diff --git a/T42Document.h b/T42Document.h
new file mode 100644
index 0000000..fd59368
--- a/dev/null
+++ b/T42Document.h
@@ -0,0 +1,81 @@
+// T42Document.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Document document
+
+class T42Document;
+class T42View;
+
+class CT42Robot {
+public:
+ T42Document* m_pDocument;
+
+ CT42Robot() : m_pDocument(NULL) {}
+ virtual ~CT42Robot() {}
+
+ virtual BOOL OnAttach(T42Document* pDocument) {
+ m_pDocument = pDocument;
+ return TRUE;
+ }
+ virtual BOOL OnDetach() { return TRUE; }
+
+ virtual BOOL OnConnect() { return TRUE; }
+ virtual BOOL OnReceive(char*,int) { return TRUE; }
+ virtual BOOL OnDisconnect() { return TRUE; }
+
+ virtual BOOL OnIPResolved() { return TRUE; }
+
+ virtual BOOL OnMinute() { return TRUE; }
+};
+
+class T42Document : public CDocument
+{
+protected:
+ T42Document(); // protected constructor used by dynamic creation
+ DECLARE_DYNCREATE(T42Document)
+
+// Attributes
+public:
+ void OnMinute();
+ BOOL m_bHidden;
+ BOOL SendOver(LPCTSTR str);
+ BOOL DetachRobot();
+ BOOL AttachRobot(CT42Robot* pRobot);
+ CT42Robot* m_pRobot;
+ void AutosaveLayout();
+ void SaveLayout();
+ T42View* m_pView;
+ void Talk(LPCTSTR from=NULL,LPCTSTR to=NULL,LPCTSTR tty=NULL,BOOL bPrompt=FALSE);
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(T42Document)
+ public:
+ virtual void Serialize(CArchive& ar); // overridden for document i/o
+ virtual void OnChangedViewList();
+ virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
+ protected:
+ virtual BOOL OnNewDocument();
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~T42Document();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(T42Document)
+ afx_msg void OnWindowSavelayout();
+ afx_msg void OnUpdateWindowAutosavelayout(CCmdUI* pCmdUI);
+ afx_msg void OnWindowAutosavelayout();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/T42Frame.cpp b/T42Frame.cpp
new file mode 100644
index 0000000..96bc522
--- a/dev/null
+++ b/T42Frame.cpp
@@ -0,0 +1,1212 @@
+// T42Frame.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42Frame.h"
+
+#include "T42View.h"
+#include "CalleeDlg.h"
+#include "shared-code/RegEx.h"
+#include "T42Document.h"
+
+#include <snmp.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Frame
+
+IMPLEMENT_DYNCREATE(T42Frame, CFrameWnd)
+
+T42Frame::T42Frame()
+{
+ VERIFY(m_hNormal=AfxGetApp()->LoadIcon(IDR_T42FRAME));
+ VERIFY(m_hFullCup=AfxGetApp()->LoadIcon(IDR_FULLT42));
+
+ m_bTrayMinimize = TRUE;
+ m_bSleepMinimize = TRUE;
+ m_bMinimizeSleep = TRUE;
+ m_onWake = wakeSound|wakePopup;
+ LoadLayout();
+
+ m_bHaveFocus = FALSE;
+ m_bTrayed = FALSE;
+ m_bSleep = FALSE;
+
+ m_asyncHandle = NULL;
+ m_resolveHandle = NULL;
+ m_ctlSocket = INVALID_SOCKET;
+ m_Socket = INVALID_SOCKET;
+ m_localEC.m_cErase = 0177;
+ m_localEC.m_kill = 025; // ^U
+ m_localEC.m_wErase = 027; // ^W
+ m_bEstablished = FALSE;
+
+ CleanUp();
+}
+
+T42Frame::~T42Frame()
+{
+}
+
+BEGIN_MESSAGE_MAP(T42Frame, CFrameWnd)
+ //{{AFX_MSG_MAP(T42Frame)
+ ON_WM_CLOSE()
+ ON_COMMAND(ID_TALK_REMOTEUSER, OnTalkRemoteuser)
+ ON_MESSAGE(WM_INITIATETALK, OnInitiateTalk)
+ ON_MESSAGE(WM_TARGETRESOLVED, OnTargetResolved)
+ ON_MESSAGE(WM_SOURCERESOLVED, OnSourceResolved)
+ ON_WM_TIMER()
+ ON_MESSAGE(WM_CTLTRANSACT, OnCTLTransact)
+ ON_MESSAGE(WM_LOOKUP_SUCCESS, OnLookupSuccess)
+ ON_MESSAGE(WM_LOOKUP_FAILURE, OnLookupFailure)
+ ON_MESSAGE(WM_ANNOUNCE_SUCCESS, OnAnnounceSuccess)
+ ON_MESSAGE(WM_ANNOUNCE_FAILURE, OnAnnounceFailure)
+ ON_MESSAGE(WM_LEAVEINVITE_SUCCESS, OnLeaveInviteSuccess)
+ ON_MESSAGE(WM_LEAVEINVITE_FAILURE, OnLeaveInviteFailure)
+ ON_MESSAGE(WM_TALKACCEPT, OnTalkAccept)
+ ON_MESSAGE(WM_LOCAL_REMOVE_SUCCESS, OnLocalRemoveSuccess)
+ ON_MESSAGE(WM_LOCAL_REMOVE_FAILURE, OnLocalRemoveFailure)
+ ON_MESSAGE(WM_REMOTE_REMOVE_SUCCESS, OnRemoteRemoveSuccess)
+ ON_MESSAGE(WM_REMOTE_REMOVE_FAILURE, OnRemoteRemoveFailure)
+ ON_MESSAGE(WM_TALK, OnTalk)
+ ON_MESSAGE(WM_TALKCHAR, OnTalkChar)
+ ON_MESSAGE(WM_TALKCONNECT, OnTalkConnect)
+ ON_WM_CREATE()
+ ON_UPDATE_COMMAND_UI(ID_INDICATOR_DATE, OnUpdateDate)
+ ON_MESSAGE(WM_EXITMENULOOP, OnExitMenuLoop)
+ ON_WM_DESTROY()
+ ON_WM_SYSCOMMAND()
+ ON_MESSAGE(WM_NAMERESOLVED, OnNameResolved)
+ ON_MESSAGE(WM_IPRESOLVED, OnIPResolved)
+ ON_WM_ACTIVATE()
+ ON_MESSAGE(WM_TRAYICON, OnTrayIcon)
+ ON_UPDATE_COMMAND_UI(ID_WINDOW_HIDEINTRAYONMINIMIZE, OnUpdateWindowHideintrayonminimize)
+ ON_COMMAND(ID_WINDOW_HIDEINTRAYONMINIMIZE, OnWindowHideintrayonminimize)
+ ON_COMMAND(ID_TALK_ABORT, OnTalkAbort)
+ ON_UPDATE_COMMAND_UI(ID_TALK_ABORT, OnUpdateTalkAbort)
+ ON_COMMAND(ID_TALK_RECONNECT, OnTalkReconnect)
+ ON_UPDATE_COMMAND_UI(ID_TALK_RECONNECT, OnUpdateTalkReconnect)
+ ON_UPDATE_COMMAND_UI(ID_TALK_REMOTEUSER, OnUpdateTalkRemoteuser)
+ ON_UPDATE_COMMAND_UI(ID_SLEEP_SLEEP, OnUpdateSleepSleep)
+ ON_COMMAND(ID_SLEEP_SLEEP, OnSleepSleep)
+ ON_UPDATE_COMMAND_UI(ID_SLEEP_SLEEPONMINIMIZE, OnUpdateSleepSleeponminimize)
+ ON_COMMAND(ID_SLEEP_SLEEPONMINIMIZE, OnSleepSleeponminimize)
+ ON_UPDATE_COMMAND_UI(ID_SLEEP_WAKEUPACTION_MAKESOUND, OnUpdateSleepWakeupactionMakesound)
+ ON_COMMAND(ID_SLEEP_WAKEUPACTION_MAKESOUND, OnSleepWakeupactionMakesound)
+ ON_UPDATE_COMMAND_UI(ID_SLEEP_WAKEUPACTION_POPUP, OnUpdateSleepWakeupactionPopup)
+ ON_COMMAND(ID_SLEEP_WAKEUPACTION_POPUP, OnSleepWakeupactionPopup)
+ ON_UPDATE_COMMAND_UI(ID_SLEEP_MINIMIZEONSLEEP, OnUpdateSleepMinimizeonsleep)
+ ON_COMMAND(ID_SLEEP_MINIMIZEONSLEEP, OnSleepMinimizeonsleep)
+ ON_COMMAND(ID_TALK_CLOSE, OnTalkClose)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Frame message handlers
+
+void T42Frame::OnClose()
+{
+ if(GetKeyState(VK_SHIFT)&0x8000){
+ T42Document* pDoc = (T42Document*)GetActiveDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+ pDoc->AutosaveLayout();
+ }
+ CFrameWnd::OnClose();
+}
+
+BOOL T42Frame::PreCreateWindow(CREATESTRUCT& cs)
+{
+CWinApp* app = AfxGetApp();
+ ASSERT(app);
+ cs.x = app->GetProfileInt("T42Window","X",cs.x);
+ cs.y = app->GetProfileInt("T42Window","Y",cs.y);
+ cs.cx = app->GetProfileInt("T42Window","Width",cs.cx);
+ cs.cy = app->GetProfileInt("T42Window","Height",cs.cy);
+
+BOOL rv = CFrameWnd::PreCreateWindow(cs);
+
+// cs.style&=~FWS_PREFIXTITLE;
+// cs.style|=FWS_ADDTOTITLE;
+
+ return rv;
+}
+
+void T42Frame::OnTalkRemoteuser()
+{
+CCalleeDlg callee(this);
+ callee.m_Callee = m_Target;
+ callee.m_Caller = m_LocalUser;
+ callee.m_TTY = m_TargetTTY;
+ if(callee.DoModal() == IDOK){
+ m_Target = callee.m_Callee;
+ m_LocalUser = callee.m_Caller;
+ m_TargetTTY = callee.m_TTY;
+ PostMessage(WM_INITIATETALK);
+ }
+}
+
+LRESULT T42Frame::OnInitiateTalk(WPARAM,LPARAM)
+{
+ if(
+ (!((T42Document*)GetActiveDocument())->m_bHidden)
+ && !m_bTrayed
+ )
+ SetForegroundWindow();
+CRegEx atRE, bangRE;
+ VERIFY(atRE.Compile("([-À-ßà-ÿ[:alnum:]_.]+)@([-[:alnum:].]+)",CRegEx::regExtended)); // u, h
+ VERIFY(bangRE.Compile("([-[:alnum:].]+)[!:]([-À-ßà-ÿ[:alnum:]._]+)",CRegEx::regExtended)); // h, u
+ if(atRE.Match(m_Target,CRegEx::regExtended)){
+ m_TargetUser = atRE.GetMatch(1);
+ m_TargetHost = atRE.GetMatch(2);
+ }else if(bangRE.Match(m_Target,CRegEx::regExtended)){
+ m_TargetUser = bangRE.GetMatch(2);
+ m_TargetHost = bangRE.GetMatch(1);
+ }else{
+ ShowMessage(IDS_ERR_MALFORMEDREMOTE,MB_ICONSTOP|MB_OK);
+ return -1;
+ }
+ SetPeerName();
+ memset(&m_TargetAddr,0,sizeof(m_TargetAddr));
+ m_TargetAddr.sin_addr.s_addr = inet_addr(m_TargetHost);
+ if(m_TargetAddr.sin_addr.s_addr == INADDR_NONE){
+ StatusLine(IDS_STATUS_RESOLVING);
+ m_asyncHandle = WSAAsyncGetHostByName(
+ m_hWnd,WM_TARGETRESOLVED,
+ (LPCTSTR)m_TargetHost,
+ (char*)m_gethostData,sizeof(m_gethostData)
+ );
+ if(!m_asyncHandle){
+ WSSystemMessage(IDS_ERR_REMOTERESOLVEFAILED,WSAGetLastError());
+ return -1;
+ }
+ // Here we're trying to establish connection using hostname (as opposed
+ // to ip address) - no further investigation needed.
+ AddToHotList();
+ }else{
+ if(!Klever::FindIFace(m_TargetAddr.sin_addr,m_SourceAddr.sin_addr))
+ m_SourceAddr.sin_addr.s_addr = INADDR_ANY;
+ PostMessage(WM_SOURCERESOLVED);
+ // Try to resolve hostname if it resolves back to the same IP - this
+ // is the canonical name we need. If not - leave it as IP.
+ m_resolveHandle = WSAAsyncGetHostByAddr(
+ m_hWnd,WM_NAMERESOLVED,
+ (char*)&m_TargetAddr.sin_addr,sizeof(m_TargetAddr.sin_addr),AF_INET,
+ (char*)m_ghResolve,sizeof(m_ghResolve)
+ );
+ if(!m_resolveHandle){
+ // We've failed to resolve hostname - leave IP - do nothing.
+ TRACE0("Failed to initiate IP resolve\n");
+ AddToHotList();
+ }
+ }
+ return 0;
+}
+
+LRESULT T42Frame::OnNameResolved(WPARAM,LPARAM lP)
+{
+ m_resolveHandle=NULL;
+ if(WSAGETASYNCERROR(lP)){
+ // We've failed to resolve hostname - leave IP - do nothing.
+ TRACE0("Failed to resolve name by ip\n");
+ AddToHotList();
+ }else{
+ hostent* he = (hostent*)m_ghResolve;
+ m_nameFromIP = he->h_name;
+ m_resolveHandle = WSAAsyncGetHostByName(
+ m_hWnd,WM_IPRESOLVED,
+ (LPCTSTR)m_nameFromIP,
+ (char*)m_ghResolve,sizeof(m_ghResolve)
+ );
+ if(!m_resolveHandle){
+ // We've failed to resolve hostname - leave IP - do nothing.
+ TRACE0("Failed to initiate name resolve\n");
+ AddToHotList();
+ }
+ }
+ return 0;
+}
+
+LRESULT T42Frame::OnIPResolved(WPARAM,LPARAM lP)
+{
+ m_resolveHandle=NULL;
+ if(WSAGETASYNCERROR(lP)){
+ // We've failed to resolve hostname - leave IP - do nothing.
+ TRACE0("Failed to resolve name by ip\n");
+ AddToHotList();
+ }else{
+ hostent* he = (hostent*)m_ghResolve;
+ if(
+ he->h_length!=sizeof(m_TargetAddr.sin_addr)
+ || he->h_addrtype!=m_TargetAddr.sin_family
+ || memcmp(*he->h_addr_list,&m_TargetAddr.sin_addr,he->h_length)
+ ){
+ // The host resolved to different IP address..
+ // maybe we should warn user about it?
+ TRACE0("IP/NAME investigations sucked in result\n");
+ AddToHotList();
+ }else{
+ // We got new hostname!! Hurray! What do we do?
+ // Yes, we set new Target..
+ m_TargetHost = m_nameFromIP;
+ m_Target = m_TargetUser + '@' + m_TargetHost;
+ SetPeerName();
+ AddToHotList();
+ T42Document* pDoc = (T42Document*)GetActiveDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+ if(pDoc->m_pRobot)
+ pDoc->m_pRobot->OnIPResolved();
+ TRACE0("IP/NAME investigations succeeded\n");
+ }
+ }
+ return 0;
+}
+
+LRESULT T42Frame::OnTargetResolved(WPARAM,LPARAM lP)
+{
+ m_asyncHandle=NULL;
+ if(WSAGETASYNCERROR(lP)){
+ WSSystemMessage(IDS_ERR_REMOTERESOLVEFAILED,WSAGetLastError());
+ return 0;
+ }
+ ASSERT(((hostent*)m_gethostData)->h_length==4);
+ memmove(&m_TargetAddr.sin_addr,*((hostent*)m_gethostData)->h_addr_list,sizeof(m_TargetAddr.sin_addr));
+ if(!Klever::FindIFace(m_TargetAddr.sin_addr,m_SourceAddr.sin_addr))
+ m_SourceAddr.sin_addr.s_addr = INADDR_ANY;
+ PostMessage(WM_SOURCERESOLVED);
+ return 0;
+}
+
+LRESULT T42Frame::OnSourceResolved(WPARAM,LPARAM)
+{
+ // Open ctl socket
+ m_SourceAddr.sin_port = 0;
+ m_SourceAddr.sin_family = AF_INET;
+ m_ctlSocket = socket(AF_INET,SOCK_DGRAM,0);
+ if(m_ctlSocket==INVALID_SOCKET){
+ WSSystemMessage(IDS_ERR_CTLCREATEFAILED,WSAGetLastError());
+ return -1;
+ }
+ if(bind(m_ctlSocket,(sockaddr*)&m_SourceAddr,sizeof(m_SourceAddr))){
+ WSSystemMessage(IDS_ERR_CTLBINDFAILED,WSAGetLastError());
+ return -1;
+ }
+int length = sizeof(m_ctlAddr);
+ if(getsockname(m_ctlSocket,(sockaddr*)&m_ctlAddr,&length)){
+ WSSystemMessage(IDS_ERR_CTLGETFAILED,WSAGetLastError());
+ return -1;
+ }
+ // Open socket for connection
+ m_SourceAddr.sin_port = 0;
+ m_SourceAddr.sin_family = AF_INET;
+ m_Socket = socket(AF_INET,SOCK_STREAM,0);
+ if(m_Socket==INVALID_SOCKET){
+ WSSystemMessage(IDS_ERR_TCPCREATEFAILED,WSAGetLastError());
+ return -1;
+ }
+ if(bind(m_Socket,(sockaddr*)&m_SourceAddr,sizeof(m_SourceAddr))){
+ WSSystemMessage(IDS_ERR_TCPBINDFAILED,WSAGetLastError());
+ return -1;
+ }
+ length = sizeof(m_SourceAddr);
+ if(getsockname(m_Socket,(sockaddr*)&m_SourceAddr,&length)){
+ WSSystemMessage(IDS_ERR_TCPGETFAILED,WSAGetLastError());
+ return -1;
+ }
+ StatusLine(IDS_STATUS_LOOKUPINVITE);
+TalkCtlMessage rq;
+ FillInMessage(rq);
+ rq.m_Type = talkCtlReqLookUp;
+ m_TargetAddr.sin_family = AF_INET;
+CT42App* app = (CT42App*)AfxGetApp();
+ m_TargetAddr.sin_port = htons(app->m_T42TalkPort);
+ VERIFY(AsyncCtlTransact(rq,m_TargetAddr,WM_LOOKUP_SUCCESS,WM_LOOKUP_FAILURE));
+ return 0;
+}
+
+BOOL T42Frame::FillInMessage(TalkCtlMessage& msg)
+{
+ memset(&msg,0,sizeof(msg));
+ msg.m_Version = talkCtlVersion;
+ msg.m_Addr = m_SourceAddr;
+ msg.m_ctlAddr = m_ctlAddr;
+ msg.m_ID = htonl(0);
+ msg.m_PID = htonl((LONG)m_hWnd);
+ ASSERT(m_LocalUser.GetLength()>0 && m_LocalUser.GetLength()<sizeof(msg.m_LName));
+ strcpy(msg.m_LName,m_LocalUser);
+ ASSERT(m_TargetUser.GetLength()>0 && m_TargetUser.GetLength()<sizeof(msg.m_RName));
+ strcpy(msg.m_RName,m_TargetUser);
+ ASSERT(m_TargetTTY.GetLength()>=0 && m_TargetTTY.GetLength()<sizeof(msg.m_RTTY));
+ strcpy(msg.m_RTTY,m_TargetTTY);
+ return TRUE;
+}
+
+BOOL T42Frame::AsyncCtlTransact(TalkCtlMessage& msg,sockaddr_in& target, UINT wmSuccess,UINT wmFailure)
+{
+ if(m_ctlSuccess || m_ctlFailure)
+ return FALSE;
+ memmove(&m_ctlTarget,&target,sizeof(m_ctlTarget));
+ memmove(&m_ctlRequest,&msg,sizeof(m_ctlRequest));
+ m_ctlSuccess = wmSuccess;
+ m_ctlFailure = wmFailure;
+ TRACE2("Initiating CTL Transaction to %s:%d\n",
+ inet_ntoa(m_ctlTarget.sin_addr),ntohs(m_ctlTarget.sin_port)
+ );
+ TRACE3("V: %d, T: %d, ID: %ld\n",
+ (int)m_ctlRequest.m_Version, (int)m_ctlRequest.m_Type,
+ ntohl(m_ctlRequest.m_ID)
+ );
+ TRACE("ADDR: %s:%d\n",
+ inet_ntoa(((sockaddr_in*)&m_ctlRequest.m_Addr)->sin_addr),
+ ntohs(((sockaddr_in*)&m_ctlRequest.m_Addr)->sin_port)
+ );
+ TRACE("CTL ADDR: %s:%d\n",
+ inet_ntoa(((sockaddr_in*)&m_ctlRequest.m_ctlAddr)->sin_addr),
+ ntohs(((sockaddr_in*)&m_ctlRequest.m_ctlAddr)->sin_port)
+ );
+ if(sendto(m_ctlSocket,(char*)&m_ctlRequest,sizeof(m_ctlRequest),0,
+ (sockaddr*)&m_ctlTarget,sizeof(m_ctlTarget))!=sizeof(m_ctlRequest)
+ ){
+ AsyncCtlTransactFailed(ctlFailSendto,WSAGetLastError());
+ return TRUE;
+ }
+ if(WSAAsyncSelect(m_ctlSocket,m_hWnd,WM_CTLTRANSACT,FD_READ)){
+ AsyncCtlTransactFailed(ctlFailSelect,WSAGetLastError());
+ return TRUE;
+ }
+ SetTimer(timerTransact,2000,NULL);
+ return TRUE;
+}
+
+LRESULT T42Frame::OnCTLTransact(WPARAM,LPARAM lP)
+{
+ KillTimer(timerTransact);
+ if(!(m_ctlSuccess && m_ctlFailure))
+ return -1;
+ if(WSAGETSELECTERROR(lP)){
+ AsyncCtlTransactFailed(ctlFailError,WSAGETSELECTERROR(lP));
+ return -1;
+ }
+ ASSERT(WSAGETSELECTEVENT(lP)&FD_READ);
+long length;
+ do{
+ if(ioctlsocket(m_ctlSocket,FIONREAD,(u_long*)&length) || length<=0)
+ break;
+ if(recv(m_ctlSocket,(char*)&m_ctlResponse,sizeof(m_ctlResponse),0)!=sizeof(m_ctlResponse))
+ continue;
+ if(
+ m_ctlResponse.m_Version != talkCtlVersion
+ || m_ctlResponse.m_Type!=m_ctlRequest.m_Type
+ )
+ continue;
+ // We got the datagram we need here
+ AsyncCtlTransactSucceeded(m_ctlResponse);
+ }while(1);
+ if(WSAAsyncSelect(m_ctlSocket,m_hWnd,WM_CTLTRANSACT,FD_READ)){
+ AsyncCtlTransactFailed(ctlFailSelect,WSAGetLastError());
+ return -1;
+ }
+ SetTimer(timerTransact,2000,NULL);
+ return 0;
+}
+
+void T42Frame::OnTimer(UINT nIDEvent)
+{
+ switch(nIDEvent){
+ case timerTransact:
+ KillTimer(timerTransact);
+ if(!(m_ctlSuccess && m_ctlFailure)){
+ TRACE0("VERY STRANGE\n");
+ break;
+ }
+ TRACE0("Transact timed out\n");
+ if(sendto(m_ctlSocket,(char*)&m_ctlRequest,sizeof(m_ctlRequest),0,
+ (sockaddr*)&m_ctlTarget,sizeof(m_ctlTarget))!=sizeof(m_ctlRequest)
+ ){
+ AsyncCtlTransactFailed(ctlFailSendto,WSAGetLastError());
+ break;
+ }
+ if(WSAAsyncSelect(m_ctlSocket,m_hWnd,WM_CTLTRANSACT,FD_READ)){
+ AsyncCtlTransactFailed(ctlFailSelect,WSAGetLastError());
+ break;
+ }
+ SetTimer(timerTransact,2000,NULL);
+ break;
+ }
+
+ CFrameWnd::OnTimer(nIDEvent);
+}
+
+
+void T42Frame::AsyncCtlTransactFailed(UINT code,LONG error)
+{
+ ASSERT(m_ctlSuccess && m_ctlFailure);
+UINT m = m_ctlFailure;
+ m_ctlFailure = m_ctlSuccess = 0;
+ WSAAsyncSelect(m_ctlSocket,NULL,0,0);
+ TRACE2("CTL Transact failed %d (%ld)\n",(int)code,error);
+ PostMessage(m,code,error);
+}
+
+void T42Frame::AsyncCtlTransactSucceeded(TalkCtlResponse& response)
+{
+ ASSERT(m_ctlSuccess && m_ctlFailure);
+UINT m = m_ctlSuccess;
+ m_ctlFailure = m_ctlSuccess = 0;
+ WSAAsyncSelect(m_ctlSocket,NULL,0,0);
+ TRACE2("CTL Transaction succeeded - A: %d, ID: %ld\n",
+ (int)response.m_Answer, ntohl(response.m_ID)
+ );
+ TRACE2("ADDR: %s:%d\n",
+ inet_ntoa(((sockaddr_in*)&response.m_Addr)->sin_addr),
+ ntohs(((sockaddr_in*)&response.m_Addr)->sin_port)
+ );
+ PostMessage(m,0,(LPARAM)&response);
+}
+
+LRESULT T42Frame::OnLookupSuccess(WPARAM,LPARAM lP)
+{
+TalkCtlResponse& rp = *(TalkCtlResponse*)lP;
+ if(rp.m_Answer==talkCtlSuccess){
+ TRACE0("Found an invitation\n");
+ if(WSAAsyncSelect(m_Socket,m_hWnd,WM_TALKCONNECT,FD_CONNECT)){
+ WSSystemMessage(IDS_ERR_TCPASELFAILED,WSAGetLastError());
+ return -1;
+ }
+ SOCKADDR_IN sin;
+ memmove(&sin,&rp.m_Addr,sizeof(sin));
+ sin.sin_family = ntohs(sin.sin_family);
+ StatusLine(IDS_STATUS_WAITINGTOCONNECT);
+ if(connect(m_Socket,(sockaddr*)&sin,sizeof(sin))){
+ if(WSAGetLastError()!=WSAEWOULDBLOCK){
+ WSSystemMessage(IDS_ERR_TCPCONNECTFAILED,WSAGetLastError());
+ return -1;
+ }
+ }else
+ PostMessage(WM_TALKCONNECT,0,WSAMAKESELECTREPLY(FD_CONNECT,0));
+ }else{
+ if(listen(m_Socket,5)){
+ WSSystemMessage(IDS_ERR_TCPLISTENFAILED,WSAGetLastError());
+ return -1;
+ }
+ if(WSAAsyncSelect(m_Socket,m_hWnd,WM_TALKACCEPT,FD_ACCEPT)){
+ WSSystemMessage(IDS_ERR_LTNASELFAILED,WSAGetLastError());
+ return -1;
+ }
+ TalkCtlMessage rq;
+ FillInMessage(rq);
+ rq.m_Type = talkCtlReqLeaveInvite;
+ rq.m_ID = htonl(-1);
+ SOCKADDR_IN tgt;
+ memmove(&tgt,&m_SourceAddr,sizeof(tgt));
+CT42App* app = (CT42App*)AfxGetApp();
+ tgt.sin_port = htons(app->m_T42TalkPort);
+ VERIFY(AsyncCtlTransact(rq,tgt,WM_LEAVEINVITE_SUCCESS,WM_LEAVEINVITE_FAILURE));
+ }
+ return 0;
+}
+LRESULT T42Frame::OnLookupFailure(WPARAM wP,LPARAM lP)
+{
+ SystemMessage(IDS_ERR_CTLLOOKUPFAILED);
+ TRACE2("Lookup failed %d, %ld",(int)wP,lP);
+ return -1;
+}
+
+LRESULT T42Frame::OnAnnounceSuccess(WPARAM,LPARAM lP)
+{
+TalkCtlResponse& rp = *(TalkCtlResponse*)lP;
+ if(rp.m_Answer != talkCtlSuccess){
+ static
+ UINT nReasons[] = {0,IDS_CTL_NOTHERE,IDS_CTL_FAILED,IDS_CTL_MACHUNKNOWN,
+ IDS_CTL_PERMISSIONDENIED, IDS_CTL_BADREQUEST, IDS_CTL_BADVERSION,
+ IDS_CTL_BADADDR, IDS_CTL_BADCTL};
+ CString reason;
+ if(rp.m_Answer<(sizeof(nReasons)/sizeof(*nReasons)))
+ SystemMessage(IDS_ERR_ANNOUNCEFAILURE,nReasons[rp.m_Answer]);
+ else
+ SystemMessage(IDS_ERR_ANNOUNCEFAILURE,IDS_CTL_UNKNOWNERROR);
+ return -1;
+ }
+ m_remoteID = rp.m_ID;
+ return 0;
+}
+LRESULT T42Frame::OnAnnounceFailure(WPARAM wP,LPARAM lP)
+{
+ SystemMessage(IDS_ERR_ANNOUNCEFAILED);
+ return -1;
+}
+
+LRESULT T42Frame::OnLeaveInviteSuccess(WPARAM,LPARAM lP)
+{
+TalkCtlResponse& rp = *(TalkCtlResponse*)lP;
+ m_localID = rp.m_ID;
+TalkCtlMessage rq;
+ FillInMessage(rq);
+ rq.m_ID = htonl(-1);
+ StatusLine(IDS_STATUS_ANNOUNCING);
+ rq.m_Type = talkCtlReqAnnounce;
+ m_TargetAddr.sin_family = AF_INET;
+CT42App* app = (CT42App*)AfxGetApp();
+ m_TargetAddr.sin_port = htons(app->m_T42TalkPort);
+ VERIFY(AsyncCtlTransact(rq,m_TargetAddr,WM_ANNOUNCE_SUCCESS,WM_ANNOUNCE_FAILURE));
+ return 0; // Or?
+}
+LRESULT T42Frame::OnLeaveInviteFailure(WPARAM wP,LPARAM lP)
+{
+ SystemMessage(IDS_ERR_LEAVINVITEFAILED);
+ TRACE2("LeaveInvite failed %d, %ld",(int)wP,lP);
+ return -1;
+}
+
+LRESULT T42Frame::OnTalkAccept(WPARAM,LPARAM lP)
+{
+ if(WSAGETSELECTERROR(lP)){
+ WSSystemMessage(IDS_ERR_TCPACCEPTFAILED,WSAGETSELECTERROR(lP));
+ return -1;
+ }
+ ASSERT(WSAGETSELECTEVENT(lP)&FD_ACCEPT);
+SOCKET s = accept(m_Socket,NULL,NULL);
+ ASSERT(s!=INVALID_SOCKET);
+ VERIFY(!closesocket(m_Socket));
+ m_Socket = s;
+ m_bConnected=TRUE;
+ SelectTalkSocket();
+ StatusLine(IDS_STATUS_WAITINGTOCONNECT);
+TalkCtlMessage rq;
+ FillInMessage(rq);
+ rq.m_Type = talkCtlReqDelete;
+ rq.m_ID = m_localID;
+SOCKADDR_IN t;
+ memmove(&t,&m_SourceAddr,sizeof(t));
+CT42App* app = (CT42App*)AfxGetApp();
+ t.sin_port = htons(app->m_T42TalkPort);
+ AsyncCtlTransact(rq,t,WM_LOCAL_REMOVE_SUCCESS,WM_LOCAL_REMOVE_FAILURE);
+ return 0;
+}
+
+LRESULT T42Frame::OnTalkConnect(WPARAM,LPARAM lP)
+{
+ if(WSAGETSELECTERROR(lP)){
+ WSSystemMessage(IDS_ERR_TCPCONNECTFAILED,WSAGETSELECTERROR(lP));
+ return -1;
+ }
+ m_bConnected=TRUE;
+ ASSERT(WSAGETSELECTEVENT(lP)&FD_CONNECT);
+ SelectTalkSocket();
+ StatusLine(IDS_STATUS_WAITINGTOCONNECT);
+ return 0;
+}
+
+LRESULT T42Frame::OnLocalRemoveSuccess(WPARAM,LPARAM lP)
+{
+TalkCtlResponse& rp = *(TalkCtlResponse*)lP;
+ ASSERT(rp.m_Answer==talkCtlSuccess);
+TalkCtlMessage rq;
+ FillInMessage(rq);
+ rq.m_Type = talkCtlReqDelete;
+ rq.m_ID = m_remoteID;
+SOCKADDR_IN t;
+ memmove(&t,&m_TargetAddr,sizeof(t));
+CT42App* app = (CT42App*)AfxGetApp();
+ t.sin_port = htons(app->m_T42TalkPort);
+ AsyncCtlTransact(rq,t,WM_REMOTE_REMOVE_SUCCESS,WM_REMOTE_REMOVE_FAILURE);
+ return 0;
+}
+LRESULT T42Frame::OnLocalRemoveFailure(WPARAM wP,LPARAM lP)
+{
+// SystemMessage(IDS_ERR_CTLLDELETEFAILED);
+ TRACE2("Local delete failed %d, %ld",(int)wP,lP);
+ return -1;
+}
+
+LRESULT T42Frame::OnRemoteRemoveSuccess(WPARAM,LPARAM lP)
+{
+TalkCtlResponse& rp = *(TalkCtlResponse*)lP;
+// ASSERT(rp.m_Answer==talkCtlSuccess); // ???
+ return 0;
+}
+LRESULT T42Frame::OnRemoteRemoveFailure(WPARAM wP,LPARAM lP)
+{
+// SystemMessage(IDS_ERR_CTLRDELETEFAILED);
+ TRACE2("Local delete failed %d, %ld",(int)wP,lP);
+ return -1;
+}
+
+LRESULT T42Frame::OnTalk(WPARAM wP,LPARAM lP)
+{
+ if(WSAGETSELECTEVENT(lP)&FD_CLOSE){
+ StatusLine(IDS_STATUS_CONNECTIONCLOSED);
+ if(WSAGETSELECTERROR(lP))
+ WSSystemMessage(IDS_ERR_CONNECTIONCLOSED,WSAGETSELECTERROR(lP));
+ else
+ SystemMessage(IDS_CONNECTIONCLOSED);
+ Established(FALSE);
+ return 0;
+ }
+ if(WSAGETSELECTERROR(lP)){
+ WSSystemMessage(IDS_ERR_TCPERROR,WSAGETSELECTERROR(lP));
+ Established(FALSE);
+ TRACE1("Error on conversation socket: %ld\n",WSAGETSELECTERROR(lP));
+ return -1;
+ }
+ if(WSAGETSELECTEVENT(lP)&FD_READ){
+ CHAR rb[512+1];
+ int rbytes = recv(m_Socket,rb,sizeof(rb)-1,0);
+ if(rbytes>0){
+ if(m_receivedEC<sizeof(m_remoteEC)){
+ int ms = min(sizeof(m_remoteEC)-m_receivedEC,rbytes);
+ memmove(
+ &((CHAR*)&m_remoteEC)[m_receivedEC],rb,ms
+ );
+ memmove(rb,&rb[ms],sizeof(rb)-ms);
+ rbytes-=ms;
+ m_receivedEC+=ms;
+ // Under some circumstances we can claim connection
+ // establishment here.
+ if(m_receivedEC==sizeof(m_remoteEC)){
+ StatusLine(IDS_STATUS_ESTABLISHED);
+ Established(TRUE);
+ }
+ }
+ if(rbytes){
+ rb[rbytes]=0;
+ T42Document* pDoc = (T42Document*)GetActiveDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+ if(pDoc->m_pRobot)
+ pDoc->m_pRobot->OnReceive(rb,rbytes);
+ PutRemote(rb);
+ if(!m_bHaveFocus){
+ SetTheIcon(m_hFullCup);
+ if(m_bSleep)
+ WakeUp();
+ }
+ }
+ }
+ }
+ if(WSAGETSELECTEVENT(lP)&FD_WRITE){
+ if(!m_bSentEC){
+ if(send(m_Socket,(char*)&m_localEC,sizeof(m_localEC),0)!=sizeof(m_localEC)){
+ WSSystemMessage(IDS_ERR_TCPERROR,WSAGetLastError());
+ Established(FALSE);
+ }else
+ m_bSentEC = TRUE;
+ }else{
+ int sb = send(m_Socket,(char*)(LPCTSTR)m_sendBuffer,m_sendBuffer.GetLength(),0);
+ if(sb<0){
+ WSSystemMessage(IDS_ERR_TCPERROR,WSAGetLastError());
+ Established(FALSE);
+ }else
+ m_sendBuffer = m_sendBuffer.Mid(sb);
+ }
+ }
+ SelectTalkSocket();
+ return 0;
+}
+
+void T42Frame::SelectTalkSocket()
+{
+ if(!m_bConnected)
+ return;
+UINT mask = FD_READ|FD_CLOSE;
+ if(!(m_bSentEC && m_sendBuffer.IsEmpty()))
+ mask|=FD_WRITE;
+ if(WSAAsyncSelect(m_Socket,m_hWnd,WM_TALK,mask)){
+ WSSystemMessage(IDS_ERR_TCPERROR,WSAGetLastError());
+ Established(FALSE);
+ }
+}
+
+BOOL T42Frame::PutRemote(LPCTSTR str)
+{
+T42View* pView = (T42View*)GetActiveView();
+ ASSERT_KINDOF(T42View,pView);
+ pView->m_remoteCtl.PutString(str);
+ return TRUE;
+}
+
+LRESULT T42Frame::OnTalkChar(WPARAM wP,LPARAM lP)
+{
+ if(wP){
+ CHAR c=(CHAR)(wP&0xFF);
+// if(c=='\r')
+//?? c='\n';
+ m_sendBuffer+=c;
+ }else{
+ CString str = (LPCTSTR)lP;
+ int cr;
+ while((cr=str.Find('\r'))>=0)
+ str = str.Left(cr)+str.Mid(cr+1);
+ m_sendBuffer+=str;
+ }
+ SelectTalkSocket();
+ return 0;
+}
+
+int T42Frame::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if(CFrameWnd::OnCreate(lpCreateStruct)==-1)
+ return -1;
+ // CG: The following block was inserted by 'Status Bar' component.
+ {
+ // Create an array for status bar indicators
+ UINT pIndicators[3] = { ID_SEPARATOR };
+ if (!m_wndStatusBar.Create(this) ||
+ !InitStatusBar(pIndicators, 1, 60))
+ {
+ TRACE0("Failed to create Status Bar\n");
+ return -1;
+ }
+ }
+
+ m_wndFake.CreateEx(
+ 0,AfxRegisterWndClass(0,0,0,0),"",WS_OVERLAPPED,
+ 0,0,0,0,
+ NULL,NULL,NULL
+ );
+
+ return 0;
+}
+
+void T42Frame::OnUpdateDate(CCmdUI* pCmdUI)
+{
+ // CG: This function was inserted by 'Status Bar' component.
+
+ // Get current date and format it
+ CTime time = CTime::GetCurrentTime();
+ CString strDate = time.Format(_T("%A, %B %d, %y "));
+
+ // BLOCK: compute the width of the date string
+ CSize size;
+ {
+ HGDIOBJ hOldFont = NULL;
+ HFONT hFont = (HFONT)m_wndStatusBar.SendMessage(WM_GETFONT);
+ CClientDC dc(NULL);
+ if (hFont != NULL)
+ hOldFont = dc.SelectObject(hFont);
+ size = dc.GetTextExtent(strDate);
+ if (hOldFont != NULL)
+ dc.SelectObject(hOldFont);
+ }
+
+ // Update the pane to reflect the current date
+ UINT nID, nStyle;
+ int nWidth;
+ m_wndStatusBar.GetPaneInfo(m_nDatePaneNo, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(m_nDatePaneNo, nID, nStyle, size.cx);
+ pCmdUI->SetText(strDate);
+ pCmdUI->Enable(TRUE);
+
+}
+
+BOOL T42Frame::InitStatusBar(UINT *pIndicators, int nSize, int nSeconds)
+{
+ // CG: This function was inserted by 'Status Bar' component.
+
+ // Create an index for the DATE pane
+ m_nDatePaneNo = nSize++;
+ pIndicators[m_nDatePaneNo] = ID_INDICATOR_DATE;
+
+ m_wndStatusBar.SetTimer(0x1000, nSeconds * 1000, NULL);
+
+ return m_wndStatusBar.SetIndicators(pIndicators, nSize);
+
+}
+
+void T42Frame::StatusLine(LPCTSTR str)
+{
+ m_wndStatusBar.SetPaneText(0,m_Status=str);
+}
+
+void T42Frame::StatusLine(UINT nID)
+{
+ VERIFY(m_Status.LoadString(nID));
+ m_wndStatusBar.SetPaneText(0,m_Status);
+}
+
+LRESULT T42Frame::OnExitMenuLoop(WPARAM,LPARAM)
+{
+ m_wndStatusBar.SetPaneText(0,m_Status);
+ return 0;
+}
+
+void T42Frame::OnDestroy()
+{
+ if(m_bTrayed){
+ NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize=sizeof(nid);
+ nid.hWnd = m_hWnd;
+ nid.uID = IDC_TRAYICON;
+ nid.uFlags = 0;
+ VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid));
+ }
+ m_wndFake.DestroyWindow();
+ CFrameWnd::OnDestroy();
+
+ CleanUp();
+}
+
+void T42Frame::ShowMessage(UINT nID,UINT flags)
+{
+CString msg;
+ VERIFY(msg.LoadString(nID));
+ ShowMessage(msg,flags);
+}
+void T42Frame::ShowMessage(LPCTSTR msg,UINT flags)
+{
+ MessageBox(msg,NULL,flags);
+}
+
+void T42Frame::Established(BOOL bEstablished)
+{
+ if(!bEstablished)
+ CleanUp();
+ else{
+ if(
+ (!((T42Document*)GetActiveDocument())->m_bHidden)
+ && !m_bTrayed
+ )
+ SetForegroundWindow();
+ }
+T42View* pView = (T42View*)GetActiveView();
+ ASSERT_KINDOF(T42View,pView);
+ pView->SetEnable(bEstablished);
+
+BOOL bRobot = (m_bEstablished && !bEstablished) || (bEstablished && !m_bEstablished);
+ m_bEstablished = bEstablished;
+
+ SetPeerName();
+ if(bRobot){
+ T42Document* pDoc = (T42Document*)pView->GetDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+ if(pDoc->m_pRobot){
+ if(bEstablished)
+ pDoc->m_pRobot->OnConnect();
+ else
+ pDoc->m_pRobot->OnDisconnect();
+ }
+ }
+}
+
+void T42Frame::CleanUp()
+{
+ if(m_resolveHandle){
+ WSACancelAsyncRequest(m_resolveHandle);
+ m_resolveHandle=NULL;
+ }
+ if(m_asyncHandle){
+ WSACancelAsyncRequest(m_asyncHandle);
+ m_asyncHandle=NULL;
+ }
+ if(m_ctlSocket!=INVALID_SOCKET){
+ closesocket(m_ctlSocket);
+ m_ctlSocket = INVALID_SOCKET;
+ }
+ if(m_Socket!=INVALID_SOCKET){
+ closesocket(m_Socket);
+ m_Socket = INVALID_SOCKET;
+ }
+
+ m_Status.LoadString(AFX_IDS_IDLEMESSAGE);
+ m_localID = m_remoteID = 0;
+ m_sendBuffer.Empty();
+ m_ctlSuccess = 0;
+ m_ctlFailure = 0;
+ m_bSentEC = FALSE;
+ m_receivedEC = 0;
+ m_bConnected=FALSE;
+}
+
+void T42Frame::OnSysCommand(UINT nID, LPARAM lParam)
+{
+ if(nID==SC_MINIMIZE){
+ if(m_bTrayMinimize){
+ NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize=sizeof(nid);
+ nid.hWnd = m_hWnd;
+ nid.uID = IDC_TRAYICON;
+ nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
+ nid.uCallbackMessage = WM_TRAYICON;
+ nid.hIcon = m_hNormal;
+ CString tip;
+ GetWindowText(tip);
+ if(tip.GetLength()>=sizeof(nid.szTip))
+ tip = tip.Left(sizeof(nid.szTip)-3)+"..";
+ strcpy(nid.szTip,(LPCTSTR)tip);
+ VERIFY(Shell_NotifyIcon(NIM_ADD,&nid));
+ CWnd* pWnd = GetNextWindow();
+ ShowWindow(SW_HIDE);
+ pWnd->SetForegroundWindow();
+ m_bTrayed=TRUE;
+ }else
+ CFrameWnd::OnSysCommand(nID, lParam);
+ if(m_bSleepMinimize)
+ m_bSleep=TRUE;
+ }else
+ CFrameWnd::OnSysCommand(nID, lParam);
+}
+
+void T42Frame::SaveLayout()
+{
+CWinApp* app = AfxGetApp();
+CRect rc;
+ GetWindowRect(rc);
+ app->WriteProfileInt("T42Window","X",rc.left);
+ app->WriteProfileInt("T42Window","Y",rc.top);
+ app->WriteProfileInt("T42Window","Width",rc.Width());
+ app->WriteProfileInt("T42Window","Height",rc.Height());
+ app->WriteProfileInt("T42Window","TrayMinimize",m_bTrayMinimize);
+ app->WriteProfileInt("T42Window","SleepMinimize",m_bSleepMinimize);
+ app->WriteProfileInt("T42Window","OnWake",m_onWake);
+ app->WriteProfileInt("T42Window","MinimizeSleep",m_bMinimizeSleep);
+}
+void T42Frame::LoadLayout()
+{
+CWinApp* app = AfxGetApp();
+ m_bTrayMinimize = app->GetProfileInt("T42Window","TrayMinimize",m_bTrayMinimize);
+ m_bSleepMinimize = app->GetProfileInt("T42Window","SleepMinimize",m_bSleepMinimize);
+ m_onWake = app->GetProfileInt("T42Window","OnWake",m_onWake);
+ m_bMinimizeSleep = app->GetProfileInt("T42Window","MinimizeSleep",m_bMinimizeSleep);
+}
+
+void T42Frame::SetPeerName(LPCTSTR str)
+{
+T42Document* pDoc = (T42Document*)GetActiveDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+CString n = str?str:m_Target;
+ pDoc->SetTitle(n);
+ m_wndFake.SetWindowText("Talk with "+n);
+}
+
+void T42Frame::OnUpdateFrameTitle(BOOL bAddToTitle)
+{
+T42Document* pDoc = (T42Document*)GetActiveDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+CString title;
+ if(bAddToTitle && pDoc && m_bEstablished)
+ title.Format(IDS_TITLE_TEAWITH,pDoc->GetTitle());
+ else
+ title.LoadString(IDS_TITLE_TEAFORTWO);
+ SetWindowText(title);
+}
+
+void T42Frame::AddToHotList(LPCTSTR str)
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ app->LastCallee(str?str:m_Target);
+}
+
+void T42Frame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
+{
+ CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
+ if(nState==WA_INACTIVE){
+ m_bHaveFocus=FALSE;
+ }else{
+ DeTray();
+ SetTheIcon(m_hNormal);
+ m_bHaveFocus=TRUE;
+ }
+}
+
+LRESULT T42Frame::OnTrayIcon(WPARAM wP,LPARAM lP)
+{
+ ASSERT(wP==IDC_TRAYICON);
+ if(lP==WM_LBUTTONDOWN)
+ SetForegroundWindow();
+ return 0;
+}
+
+void T42Frame::SetTheIcon(HICON hicon)
+{
+ SetIcon(hicon,TRUE); SetIcon(hicon,FALSE);
+ if(m_bTrayed){
+ NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize=sizeof(nid);
+ nid.hWnd = m_hWnd;
+ nid.uID = IDC_TRAYICON;
+ nid.uFlags = NIF_ICON;
+ nid.hIcon = hicon;
+ VERIFY(Shell_NotifyIcon(NIM_MODIFY,&nid));
+ }
+}
+
+void T42Frame::OnUpdateWindowHideintrayonminimize(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(m_bTrayMinimize?1:0);
+}
+void T42Frame::OnWindowHideintrayonminimize()
+{
+ m_bTrayMinimize=!m_bTrayMinimize;
+}
+
+void T42Frame::OnTalkAbort()
+{
+ ASSERT(m_Socket);
+ closesocket(m_Socket);
+ StatusLine(IDS_STATUS_CONNECTIONCLOSED);
+ SystemMessage(IDS_CONNECTIONCLOSED);
+ Established(FALSE);
+}
+void T42Frame::OnUpdateTalkAbort(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(m_bEstablished);
+}
+void T42Frame::OnTalkReconnect()
+{
+ PostMessage(WM_INITIATETALK);
+}
+void T42Frame::OnUpdateTalkReconnect(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable((!m_bEstablished) && (!m_Target.IsEmpty()));
+}
+void T42Frame::OnUpdateTalkRemoteuser(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(!m_bEstablished);
+}
+
+void T42Frame::WakeUp()
+{
+ if(m_onWake&wakeSound){
+ CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ app->StartSound(app->m_sndT42Wake);
+ }
+ if(m_onWake&wakePopup)
+ SetForegroundWindow();
+ m_bSleep=FALSE;
+}
+
+void T42Frame::OnUpdateSleepSleep(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(m_bSleep?1:0);
+}
+void T42Frame::OnSleepSleep()
+{
+ m_bSleep=!m_bSleep;
+ if(m_bSleep && m_bMinimizeSleep)
+ PostMessage(WM_SYSCOMMAND,SC_MINIMIZE);
+}
+
+void T42Frame::OnUpdateSleepSleeponminimize(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(m_bSleepMinimize?1:0);
+}
+void T42Frame::OnSleepSleeponminimize()
+{
+ m_bSleepMinimize=!m_bSleepMinimize;
+}
+
+void T42Frame::OnUpdateSleepWakeupactionMakesound(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck((m_onWake&wakeSound)?1:0);
+}
+void T42Frame::OnSleepWakeupactionMakesound()
+{
+ m_onWake^=wakeSound;
+}
+
+void T42Frame::OnUpdateSleepWakeupactionPopup(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck((m_onWake&wakePopup)?1:0);
+}
+void T42Frame::OnSleepWakeupactionPopup()
+{
+ m_onWake^=wakePopup;
+}
+
+void T42Frame::DeTray()
+{
+ if(!m_bTrayed)
+ return;
+NOTIFYICONDATA nid;
+ memset(&nid,0,sizeof(nid));
+ nid.cbSize=sizeof(nid);
+ nid.hWnd = m_hWnd;
+ nid.uID = IDC_TRAYICON;
+ nid.uFlags = 0;
+ VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid));
+ m_bTrayed=FALSE;
+ ShowWindow(SW_SHOW);
+}
+
+void T42Frame::OnUpdateSleepMinimizeonsleep(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(m_bMinimizeSleep?1:0);
+}
+void T42Frame::OnSleepMinimizeonsleep()
+{
+ m_bMinimizeSleep=!m_bMinimizeSleep;
+}
+
+void T42Frame::OnTalkClose()
+{
+ PostMessage(WM_CLOSE);
+}
+
+void T42Frame::SystemMessage(UINT nID)
+{
+CString tmp;
+ VERIFY(tmp.LoadString(nID));
+ SystemMessage(tmp);
+}
+
+void T42Frame::SystemMessage(LPCTSTR str)
+{
+T42View* pView = (T42View*)GetActiveView();
+ ASSERT_KINDOF(T42View,pView);
+ pView->SystemMessage(str);
+}
+
+void T42Frame::SystemMessage(UINT nID,UINT nIDi)
+{
+CString idi;
+ VERIFY(idi.LoadString(nIDi));
+CString tmp;
+ tmp.Format(nID,idi);
+ SystemMessage(tmp);
+}
+
+void T42Frame::WSSystemMessage(UINT nID,LONG wsaError)
+{
+UINT wsid = 0;
+ switch(wsaError){
+ case WSAENETDOWN: wsid = IDS_WSA_ENETDOWN; break;
+ case WSAECONNRESET: wsid = IDS_WSA_ECONNRESET; break;
+ case WSAECONNABORTED: wsid = IDS_WSA_ECONNABORTED; break;
+ case WSAECONNREFUSED: wsid = IDS_WSA_ECONNREFUSED; break;
+ case WSAENETUNREACH: wsid = IDS_WSA_ENETUNREACH; break;
+ case WSAETIMEDOUT: wsid = IDS_WSA_ETIMEDOUT; break;
+ case WSAHOST_NOT_FOUND: wsid = IDS_WSA_HOSTNOTFOUND; break;
+ case WSANO_DATA: wsid = IDS_WSA_NODATA; break;
+ }
+ if(wsid)
+ SystemMessage(nID,wsid);
+ else{
+ CString tmp;
+ tmp.Format("#%ld",wsaError);
+ SystemMessage(nID,tmp);
+ }
+}
+
+void T42Frame::SystemMessage(UINT nID,LPCTSTR str)
+{
+CString tmp;
+ tmp.Format(nID,str);
+ SystemMessage(tmp);
+}
+
+void T42Frame::ActivateFrame(int nCmdShow)
+{
+T42Document* pDoc = (T42Document*)GetActiveDocument();
+ ASSERT_KINDOF(T42Document,pDoc);
+ if(pDoc->m_bHidden)
+ nCmdShow=SW_HIDE;
+ CFrameWnd::ActivateFrame(nCmdShow);
+}
diff --git a/T42Frame.h b/T42Frame.h
new file mode 100644
index 0000000..9f220f1
--- a/dev/null
+++ b/T42Frame.h
@@ -0,0 +1,169 @@
+// T42Frame.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// T42Frame frame
+
+struct TalkEditChars {
+ CHAR m_cErase;
+ CHAR m_kill;
+ CHAR m_wErase;
+};
+
+class T42View;
+class T42Frame : public CFrameWnd
+{
+ DECLARE_DYNCREATE(T42Frame)
+
+// Attributes
+public:
+ BOOL m_bConnected;
+ void SystemMessage(UINT nID,LPCTSTR str);
+ void WSSystemMessage(UINT nID,LONG wsaError);
+ void SystemMessage(UINT nID,UINT nIDi);
+ void SystemMessage(LPCTSTR str);
+ void SystemMessage(UINT nID);
+ BOOL m_bMinimizeSleep;
+ void DeTray();
+ void WakeUp();
+ enum _wakeAction {
+ wakePopup = 1,
+ wakeSound = 2
+ };
+ UINT m_onWake;
+ BOOL m_bSleep;
+ BOOL m_bSleepMinimize;
+ BOOL m_bTrayed;
+ void SetTheIcon(HICON hicon);
+ BOOL m_bTrayMinimize;
+ void LoadLayout();
+ BOOL m_bHaveFocus;
+ HICON m_hFullCup;
+ HICON m_hNormal;
+ void AddToHotList(LPCTSTR str=NULL);
+ BOOL m_bEstablished;
+ virtual void OnUpdateFrameTitle(BOOL bAddToTitle);
+ void SetPeerName(LPCTSTR str=NULL);
+ void SaveLayout();
+ CString m_nameFromIP;
+ BYTE m_ghResolve[MAXGETHOSTSTRUCT];
+ HANDLE m_resolveHandle;
+ void CleanUp();
+ CWnd m_wndFake;
+ void Established(BOOL bEstablished);
+ void ShowMessage(LPCTSTR msg,UINT flags);
+ void ShowMessage(UINT nID,UINT flags);
+ void StatusLine(UINT nID);
+ CString m_Status;
+ void StatusLine(LPCTSTR str);
+ int m_nDatePaneNo;
+ CString m_sendBuffer;
+ BOOL m_bSentEC;
+ UINT m_receivedEC;
+ TalkEditChars m_localEC;
+ TalkEditChars m_remoteEC;
+ BOOL PutRemote(LPCTSTR str);
+ void SelectTalkSocket();
+ LONG m_remoteID;
+ LONG m_localID;
+ void AsyncCtlTransactSucceeded(TalkCtlResponse& response);
+ void AsyncCtlTransactFailed(UINT code,LONG error);
+ enum {
+ ctlFailSendto = 1,
+ ctlFailSelect, ctlFailError
+ };
+ UINT m_ctlSuccess;
+ UINT m_ctlFailure;
+ sockaddr_in m_ctlTarget;
+ BOOL AsyncCtlTransact(TalkCtlMessage& msg,sockaddr_in& target, UINT wmSuccess,UINT wmFailure);
+ TalkCtlMessage m_ctlRequest;
+ TalkCtlResponse m_ctlResponse;
+ CString m_TargetTTY;
+ CString m_LocalUser;
+ BOOL FillInMessage(TalkCtlMessage& msg);
+ SOCKET m_Socket;
+ SOCKADDR_IN m_ctlAddr;
+ SOCKET m_ctlSocket;
+ SOCKADDR_IN m_SourceAddr;
+ SOCKADDR_IN m_TargetAddr;
+ BYTE m_gethostData[MAXGETHOSTSTRUCT];
+ HANDLE m_asyncHandle;
+ CString m_TargetHost;
+ CString m_TargetUser;
+ CString m_Target;
+
+// Operations
+public:
+ T42Frame(); // protected constructor used by dynamic creation
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(T42Frame)
+ public:
+ virtual void ActivateFrame(int nCmdShow = -1);
+ protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ CStatusBar m_wndStatusBar;
+ virtual ~T42Frame();
+public:
+ // Generated message map functions
+ //{{AFX_MSG(T42Frame)
+ afx_msg void OnClose();
+ afx_msg void OnTalkRemoteuser();
+ afx_msg LRESULT OnInitiateTalk(WPARAM,LPARAM);
+ afx_msg LRESULT OnTargetResolved(WPARAM,LPARAM);
+ afx_msg LRESULT OnSourceResolved(WPARAM,LPARAM);
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg LRESULT OnCTLTransact(WPARAM,LPARAM);
+ afx_msg LRESULT OnLookupSuccess(WPARAM,LPARAM);
+ afx_msg LRESULT OnLookupFailure(WPARAM,LPARAM);
+ afx_msg LRESULT OnAnnounceSuccess(WPARAM,LPARAM);
+ afx_msg LRESULT OnAnnounceFailure(WPARAM,LPARAM);
+ afx_msg LRESULT OnLeaveInviteSuccess(WPARAM,LPARAM);
+ afx_msg LRESULT OnLeaveInviteFailure(WPARAM,LPARAM);
+ afx_msg LRESULT OnTalkAccept(WPARAM,LPARAM);
+ afx_msg LRESULT OnLocalRemoveSuccess(WPARAM,LPARAM);
+ afx_msg LRESULT OnLocalRemoveFailure(WPARAM,LPARAM);
+ afx_msg LRESULT OnRemoteRemoveSuccess(WPARAM,LPARAM);
+ afx_msg LRESULT OnRemoteRemoveFailure(WPARAM,LPARAM);
+ afx_msg LRESULT OnTalk(WPARAM,LPARAM);
+ afx_msg LRESULT OnTalkChar(WPARAM,LPARAM);
+ afx_msg LRESULT OnTalkConnect(WPARAM,LPARAM);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnUpdateDate(CCmdUI* pCmdUI);
+ afx_msg LRESULT OnExitMenuLoop(WPARAM,LPARAM);
+ afx_msg void OnDestroy();
+ afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+ afx_msg LRESULT OnNameResolved(WPARAM,LPARAM);
+ afx_msg LRESULT OnIPResolved(WPARAM,LPARAM);
+ afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
+ afx_msg LRESULT OnTrayIcon(WPARAM,LPARAM);
+ afx_msg void OnUpdateWindowHideintrayonminimize(CCmdUI* pCmdUI);
+ afx_msg void OnWindowHideintrayonminimize();
+ afx_msg void OnTalkAbort();
+ afx_msg void OnUpdateTalkAbort(CCmdUI* pCmdUI);
+ afx_msg void OnTalkReconnect();
+ afx_msg void OnUpdateTalkReconnect(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateTalkRemoteuser(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateSleepSleep(CCmdUI* pCmdUI);
+ afx_msg void OnSleepSleep();
+ afx_msg void OnUpdateSleepSleeponminimize(CCmdUI* pCmdUI);
+ afx_msg void OnSleepSleeponminimize();
+ afx_msg void OnUpdateSleepWakeupactionMakesound(CCmdUI* pCmdUI);
+ afx_msg void OnSleepWakeupactionMakesound();
+ afx_msg void OnUpdateSleepWakeupactionPopup(CCmdUI* pCmdUI);
+ afx_msg void OnSleepWakeupactionPopup();
+ afx_msg void OnUpdateSleepMinimizeonsleep(CCmdUI* pCmdUI);
+ afx_msg void OnSleepMinimizeonsleep();
+ afx_msg void OnTalkClose();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+private:
+ BOOL InitStatusBar(UINT *pIndicators, int nSize, int nSeconds);
+};
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/T42Secretary.cpp b/T42Secretary.cpp
new file mode 100644
index 0000000..62cef87
--- a/dev/null
+++ b/T42Secretary.cpp
@@ -0,0 +1,121 @@
+// T42Secretary.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42Document.h"
+#include "T42Secretary.h"
+
+#include "T42View.h"
+#include "T42Frame.h"
+
+CT42Secretary::CT42Secretary()
+{
+ m_logEntry.m_Time = CTime::GetCurrentTime();
+CT42App* app = (CT42App*)AfxGetApp();
+ app->m_T42LinesBusy++;
+ m_limitTime = app->m_T42STimeLimit;
+ m_limitBytes = app->m_T42SBytesLimit;
+ TRACE0("Secretary++\n");
+}
+
+CT42Secretary::~CT42Secretary()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ app->m_T42LinesBusy--;
+ TRACE0("Secretary--\n");
+}
+
+
+BOOL CT42Secretary::OnAttach(T42Document* pDocument)
+{
+ TRACE0("T42S - OnAttach\n");
+ return CT42Robot::OnAttach(pDocument);
+}
+
+BOOL CT42Secretary::OnConnect()
+{
+ m_logEntry.m_Caller = m_pDocument->m_pView->m_pFrame->m_Target;
+ m_logEntry.m_Callee = m_pDocument->m_pView->m_pFrame->m_LocalUser;
+ m_logEntry.m_Message.Empty();
+ m_logEntry.m_Time = CTime::GetCurrentTime();
+
+CT42App* app = (CT42App*)AfxGetApp();
+CString greet = app->m_T42SGreeting;
+int ix;
+ while((ix=greet.Find("%t"))>=0){
+ CString tmp;
+ tmp.Format("%lu",app->m_T42STimeLimit.GetTotalSeconds()/60);
+ greet = greet.Left(ix)+tmp+greet.Mid(ix+2);
+ }
+ while((ix=greet.Find("%c"))>=0){
+ CString tmp;
+ tmp.Format("%u",app->m_T42SBytesLimit);
+ greet = greet.Left(ix)+tmp+greet.Mid(ix+2);
+ }
+ m_pDocument->SendOver(greet);
+ return TRUE;
+}
+
+BOOL CT42Secretary::OnReceive(char* pData,int nBytes)
+{
+ if(m_limitBytes && m_pDocument->m_pView->m_remoteCtl.GetTextLength()>=m_limitBytes)
+ OnDisconnect();
+ return TRUE;
+}
+
+BOOL CT42Secretary::OnDisconnect()
+{
+ m_logEntry.m_Duration = CTime::GetCurrentTime()-m_logEntry.m_Time;
+EDITSTREAM es;
+ memset(&es,0,sizeof(es));
+ es.dwCookie = (DWORD)&m_logEntry.m_Message;
+ es.pfnCallback = ESINProc;
+ m_pDocument->m_pView->m_remoteCtl.StreamOut(SF_RTF,es);
+ m_logEntry.m_Status = CT42CallLogEntry::statusOk;
+CT42App* app = (CT42App*)AfxGetApp();
+ VERIFY(app->AddT42Call(m_logEntry));
+ m_pDocument->m_pView->m_pFrame->OnTalkClose();
+ return TRUE;
+}
+
+BOOL CT42Secretary::OnDetach()
+{
+ TRACE0("T42S - OnDetach\n");
+ delete this;
+ return TRUE;
+}
+
+
+BOOL CT42Secretary::OnIPResolved()
+{
+ m_logEntry.m_Caller = m_pDocument->m_pView->m_pFrame->m_Target;
+ return TRUE;
+}
+
+DWORD CALLBACK CT42Secretary::ESINProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb)
+{
+CString* str = (CString*)dwCookie;
+ if(memchr(pbBuff,0,cb-1)){
+ (*pcb) = 0;
+ return 1;
+ }
+UINT p = str->GetLength();
+CHAR* s = str->GetBuffer(p+cb+1);
+ memmove(&s[p],pbBuff,cb);
+ s[p+cb]=0;
+ str->ReleaseBuffer();
+ (*pcb)=cb;
+ return 0;
+}
+
+BOOL CT42Secretary::OnMinute()
+{
+ if(
+ m_limitTime.GetTotalSeconds() &&
+ (CTime::GetCurrentTime()-m_logEntry.m_Time)>=m_limitTime
+ )
+ OnDisconnect();
+ return TRUE;
+}
+
diff --git a/T42Secretary.h b/T42Secretary.h
new file mode 100644
index 0000000..97d1440
--- a/dev/null
+++ b/T42Secretary.h
@@ -0,0 +1,17 @@
+class CT42Secretary : public CT42Robot {
+public:
+ virtual ~CT42Secretary();
+ BOOL OnMinute();
+ UINT m_limitBytes;
+ CTimeSpan m_limitTime;
+ static DWORD CALLBACK ESINProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb);
+ BOOL OnIPResolved();
+ CT42Secretary();
+ CT42CallLogEntry m_logEntry;
+ BOOL OnDetach();
+ BOOL OnDisconnect();
+ BOOL OnReceive(char* pData,int nBytes);
+ BOOL OnConnect();
+ BOOL OnAttach(T42Document* pDocument);
+};
+
diff --git a/T42View.cpp b/T42View.cpp
new file mode 100644
index 0000000..8ccad1c
--- a/dev/null
+++ b/T42View.cpp
@@ -0,0 +1,703 @@
+// T42View.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "T42.h"
+#include "T42View.h"
+
+#include "T42Frame.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// T42View
+
+IMPLEMENT_DYNCREATE(T42View, CFormView)
+
+T42View::T42View()
+ : CFormView(T42View::IDD)
+{
+ //{{AFX_DATA_INIT(T42View)
+ //}}AFX_DATA_INIT
+ m_localCtl.m_pView = m_remoteCtl.m_pView = this;
+ m_pFrame = NULL;
+ m_localSize = 50;
+ m_remoteSize = 50;
+ m_gapSize = 5;
+ m_Ort = ortHorizontal;
+ m_bShown = FALSE;
+ m_bTracking = FALSE;
+ m_hHorzCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENS);
+ m_hVertCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
+ m_bEnabled = FALSE;
+}
+
+T42View::~T42View()
+{
+}
+
+void T42View::DoDataExchange(CDataExchange* pDX)
+{
+ CFormView::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(T42View)
+ DDX_Control(pDX, IDC_SPLIT, m_splitCtl);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(T42View, CFormView)
+ //{{AFX_MSG_MAP(T42View)
+ ON_WM_SIZE()
+ ON_MESSAGE(WM_SPLITTERBDOWN, OnSplitterBDown)
+ ON_WM_MOUSEMOVE()
+ ON_WM_LBUTTONUP()
+ ON_WM_SETCURSOR()
+ ON_COMMAND(ID_WINDOW_SPLITEQUALLY, OnWindowSplitequally)
+ ON_UPDATE_COMMAND_UI(ID_WINDOW_HORIZONTALSPLIT, OnUpdateWindowHorizontalsplit)
+ ON_UPDATE_COMMAND_UI(ID_WINDOW_VERTICALSPLIT, OnUpdateWindowVerticalsplit)
+ ON_COMMAND(ID_WINDOW_HORIZONTALSPLIT, OnWindowHorizontalsplit)
+ ON_COMMAND(ID_WINDOW_VERTICALSPLIT, OnWindowVerticalsplit)
+ ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
+ ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
+ ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
+ ON_WM_CANCELMODE()
+ ON_UPDATE_COMMAND_UI(ID_TEA_SAVE, OnUpdateTeaSave)
+ ON_COMMAND(ID_TEA_SAVE, OnTeaSave)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// T42View diagnostics
+
+#ifdef _DEBUG
+void T42View::AssertValid() const
+{
+ CFormView::AssertValid();
+}
+
+void T42View::Dump(CDumpContext& dc) const
+{
+ CFormView::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// T42View message handlers
+/////////////////////////////////////////////////////////////////////////////
+// CSplitBar
+
+CSplitBar::CSplitBar()
+{
+}
+
+CSplitBar::~CSplitBar()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CSplitBar, CStatic)
+ //{{AFX_MSG_MAP(CSplitBar)
+ ON_WM_LBUTTONDOWN()
+ ON_WM_PAINT()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSplitBar message handlers
+
+void CSplitBar::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ GetParent()->PostMessage(WM_SPLITTERBDOWN);
+}
+
+void CSplitBar::OnPaint()
+{
+CPaintDC dc(this); // device context for painting
+CRect rc;
+ GetWindowRect(rc);
+ ScreenToClient(rc);
+ dc.DrawEdge(rc,EDGE_RAISED,(m_Ort==T42View::ortVertical)?BF_LEFT|BF_RIGHT:BF_TOP|BF_BOTTOM);
+}
+
+void T42View::OnInitialUpdate()
+{
+ CFormView::OnInitialUpdate();
+ m_pFrame = (T42Frame*)GetParent();
+ ASSERT_KINDOF(T42Frame,m_pFrame);
+ SetScaleToFitSize(CSize(10,10));
+
+ m_localCtl.Create(WS_CHILD|WS_VISIBLE|ES_AUTOVSCROLL|ES_LEFT|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL,
+ CRect(0,0,0,0), this, 0);
+ m_remoteCtl.Create(WS_CHILD|WS_VISIBLE|ES_AUTOVSCROLL|ES_LEFT|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL,
+ CRect(0,0,0,0), this, 0);
+ m_localCtl.SetFocus();
+ m_localCtl.m_pInTEC = &m_pFrame->m_localEC;
+ m_localCtl.m_pOuTEC = &m_pFrame->m_remoteEC;
+ m_remoteCtl.m_pInTEC = &m_pFrame->m_remoteEC;
+ m_remoteCtl.m_pOuTEC = &m_pFrame->m_localEC;
+
+
+ LoadLayout();
+
+ RecalcLayout();
+ m_bShown=TRUE;
+}
+
+void T42View::RecalcLayout()
+{
+UINT lrs = m_localSize+m_remoteSize;
+ m_splitCtl.m_Ort = m_Ort;
+CRect crc;
+ GetClientRect(crc);
+CRect rc;
+UINT ls = m_localSize, rs = m_remoteSize;
+ if(m_Ort==ortHorizontal){
+ UINT lr = crc.Height()-m_gapSize;
+ rc.top = rc.left = 0;
+ rc.right = crc.right;
+
+ ls = lr*m_localSize/lrs;
+ rc.bottom = ls;
+ m_localCtl.MoveWindow(rc);
+
+ rc.top=rc.bottom+1;
+ rc.bottom=rc.top+m_gapSize-1;
+ m_splitCtl.MoveWindow(rc);
+
+ rc.top=rc.bottom+1;
+ rc.bottom=crc.bottom;
+ rs = rc.Height();
+ m_remoteCtl.MoveWindow(rc);
+ }else if(m_Ort==ortVertical){
+ CRect crc;
+ GetClientRect(crc);
+ CRect rc;
+ UINT lr = crc.Width()-m_gapSize;
+ rc.top = rc.left = 0;
+ rc.bottom = crc.bottom;
+
+ ls = lr*m_localSize/lrs;
+ rc.right = ls;
+ m_localCtl.MoveWindow(rc);
+
+ rc.left=rc.right+1;
+ rc.right=rc.left+m_gapSize-1;
+ m_splitCtl.MoveWindow(rc);
+
+ rc.left=rc.right+1;
+ rc.right=crc.right;
+ rs = rc.Width();
+ m_remoteCtl.MoveWindow(rc);
+ }else
+ ASSERT(FALSE);
+ m_localSize = ls; m_remoteSize = rs;
+}
+
+void T42View::OnSize(UINT nType, int cx, int cy)
+{
+ CFormView::OnSize(nType, cx, cy);
+ if(m_bShown)
+ RecalcLayout();
+}
+
+LRESULT T42View::OnSplitterBDown(WPARAM,LPARAM)
+{
+ SetCapture();
+ m_bTracking = TRUE;
+CRect rc;
+ GetClientRect(rc);
+ if(m_Ort==ortHorizontal){
+ ASSERT(rc.Height()>25);
+ rc.top+=10;
+ rc.bottom-=10;
+ }else{
+ ASSERT(rc.Width()>25);
+ rc.left+=10;
+ rc.right-=10;
+ }
+ ClientToScreen(rc);
+ ClipCursor(&rc);
+ return 0;
+}
+
+void T42View::OnMouseMove(UINT nFlags, CPoint point)
+{
+ if(m_bTracking){
+ CRect rc;
+ GetClientRect(rc);
+ if(m_Ort==ortHorizontal){
+ m_localSize = point.y;
+ m_remoteSize = rc.bottom-point.y;
+ }else{
+ m_localSize = point.x;
+ m_remoteSize = rc.right-point.x;
+ }
+ RecalcLayout();
+ }
+
+ CFormView::OnMouseMove(nFlags, point);
+}
+
+void T42View::OnLButtonUp(UINT nFlags, CPoint point)
+{
+ if(m_bTracking){
+ ClipCursor(NULL);
+ m_bTracking=FALSE;
+ ReleaseCapture();
+ }
+ CFormView::OnLButtonUp(nFlags, point);
+}
+/////////////////////////////////////////////////////////////////////////////
+// CLocalCtl
+
+CLocalCtl::CLocalCtl()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ m_bgColor = app->m_crT42LocalBG;
+ memmove(&m_fmtUser,&app->m_fmtT42Local,sizeof(m_fmtUser));
+ memmove(&m_fmtSystem,&app->m_fmtT42System,sizeof(m_fmtSystem));
+}
+
+CLocalCtl::~CLocalCtl()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CLocalCtl, CRichTalkCtl)
+ //{{AFX_MSG_MAP(CLocalCtl)
+ ON_WM_CREATE()
+ ON_WM_CHAR()
+ ON_WM_KEYDOWN()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CLocalCtl message handlers
+/////////////////////////////////////////////////////////////////////////////
+// CRemoteCtl
+
+CRemoteCtl::CRemoteCtl()
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ m_bgColor = app->m_crT42RemoteBG;
+ memmove(&m_fmtUser,&app->m_fmtT42Remote,sizeof(m_fmtUser));
+ memmove(&m_fmtSystem,&app->m_fmtT42System,sizeof(m_fmtSystem));
+}
+
+CRemoteCtl::~CRemoteCtl()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CRemoteCtl, CRichTalkCtl)
+ //{{AFX_MSG_MAP(CRemoteCtl)
+ ON_WM_CREATE()
+ ON_WM_CHAR()
+ ON_WM_KEYDOWN()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CRemoteCtl message handlers
+
+void CRichTalkCtl::Setup()
+{
+ ModifyStyle(0,WS_VSCROLL);
+ SetOptions(ECOOP_SET,ECO_AUTOWORDSELECTION|ECO_AUTOVSCROLL|ECO_READONLY|
+ ECO_WANTRETURN|ECO_SAVESEL|ECO_SELECTIONBAR|ECO_NOHIDESEL);
+ SetTargetDevice(NULL,0);
+ SetSel(0,-1);
+PARAFORMAT pf;
+ memset(&pf,0,sizeof(pf));
+ pf.cbSize = sizeof(pf);
+ pf.dwMask = PFM_OFFSET;
+ pf.dxOffset = 20;
+ SetParaFormat(pf);
+ SetDefaultCharFormat(m_fmtUser);
+ SetSelectionCharFormat(m_fmtUser);
+ SetSel(-1,-1);
+ SetColor();
+}
+
+int CRemoteCtl::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CRichEditCtrl::OnCreate(lpCreateStruct) == -1)
+ return -1;
+ Setup();
+ return 0;
+}
+
+int CLocalCtl::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CRichEditCtrl::OnCreate(lpCreateStruct) == -1)
+ return -1;
+ Setup();
+ return 0;
+}
+
+void CLocalCtl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ if(!m_pView->m_bEnabled)
+ return;
+ if(!(nFlags&0x8000)){
+ ASSERT(m_pView && m_pView->m_pFrame);
+ if(nChar=='\r')
+ nChar='\n';
+ UINT c = nChar;
+ if(c=='\b')
+ c=m_pOuTEC->m_cErase;
+ m_pView->m_pFrame->PostMessage(WM_TALKCHAR,c);
+ PutCharacter(nChar);
+ }
+}
+
+void CRemoteCtl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ if(!m_pView->m_bEnabled)
+ return;
+ if(!(nFlags&0x8000)){
+ ASSERT(m_pView && m_pView->m_pFrame);
+ if(nChar=='\r')
+ nChar='\n';
+ UINT c = nChar;
+ if(c=='\b')
+ c=m_pOuTEC->m_cErase;
+ m_pView->m_pFrame->PostMessage(WM_TALKCHAR,c);
+ m_pView->m_localCtl.SetFocus();
+ m_pView->m_localCtl.PutCharacter(nChar);
+ }
+}
+
+void CRichTalkCtl::PutString(LPCTSTR str)
+{
+CString s = str;
+CHAR span[] = { '\r','\n','\a','\b',m_pInTEC->m_cErase,0 };
+CString sss;
+ while(!s.IsEmpty()){
+ sss=s.SpanExcluding(span);
+ if(!sss.IsEmpty()){
+ BOOL bDo = !GetTextLength();
+ SetSel(-1,-1);
+ long ss,es;
+ if(bDo)
+ GetSel(ss,es);
+ ReplaceSel(sss);
+ if(bDo){
+ SetSel(ss,-1);
+ SetSelectionCharFormat(m_fmtUser);
+ SetSel(-1,-1);
+ }
+ s = s.Mid(sss.GetLength());
+ }
+ if(!s.IsEmpty()){
+ PutCharacter(s[0]);
+ s=s.Mid(1);
+ }
+ }
+ UnlockWindowUpdate();
+}
+
+void CRichTalkCtl::PutCharacter(CHAR c)
+{
+ if(c=='\r')
+ return;
+ if(c=='\a'){
+ CT42App* app = (CT42App*)AfxGetApp();
+ ASSERT(app);
+ app->StartSound(app->m_sndT42Bell);
+ return;
+ }else if(c=='\b' || c==m_pInTEC->m_cErase){
+ SetSel(-1,-1);
+ CHARRANGE cr;
+ GetSel(cr);
+ if(cr.cpMin>0){
+ cr.cpMin--;
+ SetSel(cr);
+ ReplaceSel("");
+ }else
+ MessageBeep(0xFFFFFFFF);
+ return;
+ }
+BOOL bDo = !GetTextLength();
+ SetSel(-1,-1);
+char tmp[2] = {c,0};
+long ss,es;
+ if(bDo)
+ GetSel(ss,es);
+ ReplaceSel(tmp);
+ if(bDo){
+ SetSel(ss,-1);
+ SetSelectionCharFormat(m_fmtUser);
+ SetSel(-1,-1);
+ }
+ UnlockWindowUpdate();
+}
+
+void CRichTalkCtl::SystemMessage(LPCTSTR str)
+{
+ SetSel(-1,-1);
+
+ if(
+ GetTextLength()
+ && LineLength()
+ )
+ ReplaceSel("\n");
+
+CString tmp = "[";
+ tmp+=str;
+ tmp+=']';
+long ss,es;
+ GetSel(ss,es);
+ ReplaceSel(tmp);
+ SetSel(ss,-1);
+ SetSelectionCharFormat(m_fmtSystem);
+ SetSel(-1,-1);
+ GetSel(ss,es);
+ ReplaceSel("\n");
+ SetSel(ss,-1);
+ SetSelectionCharFormat(m_fmtUser);
+ SetSel(-1,-1);
+ UnlockWindowUpdate();
+}
+
+BOOL T42View::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
+{
+BOOL rv = CFormView::OnSetCursor(pWnd, nHitTest, message);
+ if(rv)
+ return rv;
+ if(pWnd==&m_splitCtl){
+ if(m_Ort==ortVertical){
+ SetCursor(m_hVertCursor);
+ }else{
+ SetCursor(m_hHorzCursor);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void CLocalCtl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ CRichTalkCtl::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CRichTalkCtl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ switch(nChar){
+ case VK_INSERT:
+ case VK_DELETE:
+ case VK_BACK:
+ case VK_ESCAPE:
+ return;
+ }
+ CRichEditCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CRemoteCtl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ CRichTalkCtl::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void T42View::OnWindowSplitequally()
+{
+ m_localSize = m_remoteSize = 50;
+ RecalcLayout();
+}
+
+void T42View::OnUpdateWindowHorizontalsplit(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetRadio(m_Ort==ortHorizontal);
+}
+
+void T42View::OnUpdateWindowVerticalsplit(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetRadio(m_Ort==ortVertical);
+}
+
+void T42View::OnWindowHorizontalsplit()
+{
+ m_Ort = ortHorizontal;
+ RecalcLayout();
+}
+
+void T42View::OnWindowVerticalsplit()
+{
+ m_Ort = ortVertical;
+ RecalcLayout();
+}
+
+
+void T42View::SetEnable(BOOL bEnable)
+{
+ m_bEnabled = bEnable;
+ m_localCtl.SetColor();
+ m_remoteCtl.SetColor();
+}
+
+void CRichTalkCtl::SetColor()
+{
+ if(m_pView->m_bEnabled)
+ SetBackgroundColor(FALSE,m_bgColor);
+ else{
+ SetBackgroundColor(
+ FALSE,
+ RGB(
+ GetRValue(m_bgColor)/2,
+ GetGValue(m_bgColor)/2,
+ GetBValue(m_bgColor)/2
+ )
+ );
+ }
+}
+
+void T42View::OnEditCopy()
+{
+CWnd* pWnd = GetFocus();
+ if(pWnd==&m_localCtl)
+ m_localCtl.Copy();
+ else if(pWnd==&m_remoteCtl)
+ m_remoteCtl.Copy();
+ else
+ MessageBeep(MB_OK);
+}
+
+void T42View::OnEditPaste()
+{
+ ASSERT(m_pFrame);
+ if(!m_bEnabled)
+ return;
+ if(!IsClipboardFormatAvailable(CF_TEXT))
+ return;
+ if(!OpenClipboard())
+ return;
+HANDLE h = GetClipboardData(CF_TEXT);
+LPVOID gl = GlobalLock(h);
+ ASSERT(gl);
+ m_pFrame->SendMessage(WM_TALKCHAR,0,(LPARAM)gl);
+ m_localCtl.PutString((LPCTSTR)gl);
+ GlobalUnlock(h);
+ CloseClipboard();
+}
+
+void T42View::OnUpdateEditPaste(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(m_bEnabled && IsClipboardFormatAvailable(CF_TEXT));
+}
+
+void T42View::SaveLayout()
+{
+CWinApp* app = AfxGetApp();
+ app->WriteProfileInt("T42View","LocalSize",m_localSize);
+ app->WriteProfileInt("T42View","RemoteSize",m_remoteSize);
+ app->WriteProfileInt("T42View","Orientation",m_Ort);
+}
+
+void T42View::OnCancelMode()
+{
+ CFormView::OnCancelMode();
+ if(m_bTracking){
+ ClipCursor(NULL);
+ m_bTracking=FALSE;
+ ReleaseCapture();
+ }
+}
+
+void T42View::LoadLayout()
+{
+CWinApp* app = AfxGetApp();
+ m_localSize = app->GetProfileInt("T42View","LocalSize",m_localSize);
+ m_remoteSize = app->GetProfileInt("T42View","RemoteSize",m_remoteSize);
+_orientation ortSave = m_Ort;
+ m_Ort = (_orientation)app->GetProfileInt("T42View","Orientation",m_Ort);
+ if(m_Ort!=ortHorizontal && m_Ort!=ortVertical)
+ m_Ort=ortSave;
+}
+
+void T42View::SystemMessage(LPCTSTR str)
+{
+CT42App* app = (CT42App*)AfxGetApp();
+ m_localCtl.SystemMessage(str);
+ m_remoteCtl.SystemMessage(str);
+}
+
+
+void T42View::OnUpdateTeaSave(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(m_localCtl.GetTextLength() || m_remoteCtl.GetTextLength());
+}
+
+void T42View::OnTeaSave()
+{
+CString dfn;
+ dfn.Format(IDS_FILENAME_T42, m_pFrame->m_LocalUser,m_pFrame->m_Target);
+CString filter;
+ VERIFY(filter.LoadString(IDS_FILTER_RTF));
+CFileDialog fd(FALSE,".rtf",dfn,
+ OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER|
+ OFN_LONGNAMES|OFN_NOREADONLYRETURN|OFN_PATHMUSTEXIST,
+ filter,this
+ );
+ if(fd.DoModal()==IDOK){
+ try{
+ CStdioFile f(fd.GetPathName(),
+ CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite|
+ CFile::typeText);
+ CString rtf;
+ rtf.Format(IDS_RTF_HEAD,m_pFrame->m_LocalUser,m_pFrame->m_Target);
+ f.WriteString(rtf);
+ CMemFile mf(2048);
+ EDITSTREAM es;
+ memset(&es,0,sizeof(es));
+ es.dwCookie = (DWORD)&mf;
+ es.pfnCallback = ESINProc;
+ m_localCtl.StreamOut(SF_RTF,es);
+ UINT tmp=0;
+ mf.Write(&tmp,1);
+ LONG bytes = mf.GetLength();
+ LPBYTE pd = mf.Detach();
+ LPTSTR str;
+ while(str = strstr((LPCTSTR)pd,"\\rtf1"))memmove(str,&str[5],strlen(str)-4);
+ while(str = strstr((LPCTSTR)pd,"\\pard"))memmove(str,&str[5],strlen(str)-4);
+ f.Write(pd,strlen((LPCTSTR)pd));
+ rtf.LoadString(IDS_RTF_DELIMITER);
+ f.WriteString(rtf);
+ mf.Attach(pd,bytes,2048);
+ memset(&es,0,sizeof(es));
+ es.dwCookie = (DWORD)&mf;
+ es.pfnCallback = ESINProc;
+ m_remoteCtl.StreamOut(SF_RTF,es);
+ mf.Write(&tmp,1);
+ bytes = mf.GetLength();
+ pd = mf.Detach();
+ while(str = strstr((LPCTSTR)pd,"\\rtf1"))memmove(str,&str[5],strlen(str)-4);
+ while(str = strstr((LPCTSTR)pd,"\\pard"))memmove(str,&str[5],strlen(str)-4);
+ f.Write(pd,strlen((LPCTSTR)pd));
+ rtf.LoadString(IDS_RTF_TAIL);
+ f.WriteString(rtf);
+ delete pd;
+ f.Close();
+ }catch(CException* e){
+ TRACE0("Write exception\n");
+ e->Delete();
+ }
+ }
+}
+
+DWORD CALLBACK T42View::ESINProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb)
+{
+CFile* f = (CFile*)dwCookie;
+ try{
+ f->Write(pbBuff,cb);
+ (*pcb)=cb;
+ }catch(CException* e){
+ e->Delete();
+ TRACE0("Save Exception\n");
+ (*pcb)=0;
+ return 1;
+ }
+ return 0;
+}
diff --git a/T42View.h b/T42View.h
new file mode 100644
index 0000000..f41fb1e
--- a/dev/null
+++ b/T42View.h
@@ -0,0 +1,220 @@
+// T42View.h : header file
+//
+
+class T42View;
+class T42Frame;
+struct TalkEditChars;
+class CRichTalkCtl : public CRichEditCtrl {
+public:
+ void SystemMessage(LPCTSTR str);
+ TalkEditChars* m_pInTEC;
+ TalkEditChars* m_pOuTEC;
+ T42View* m_pView;
+ COLORREF m_bgColor;
+ CHARFORMAT m_fmtSystem;
+ CHARFORMAT m_fmtUser;
+ void SetColor();
+ void Setup();
+ void PutString(LPCTSTR str);
+ void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ void PutCharacter(CHAR c);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CLocalCtl window
+
+class CLocalCtl : public CRichTalkCtl
+{
+// Construction
+public:
+ CLocalCtl();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CLocalCtl)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CLocalCtl();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CLocalCtl)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// CRemoteCtl window
+
+class CRemoteCtl : public CRichTalkCtl
+{
+// Construction
+public:
+ CRemoteCtl();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRemoteCtl)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CRemoteCtl();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CRemoteCtl)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// CSplitBar window
+
+class CSplitBar : public CStatic
+{
+// Construction
+public:
+ CSplitBar();
+
+// Attributes
+public:
+ int m_Ort;
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CSplitBar)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CSplitBar();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CSplitBar)
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnPaint();
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// T42View form view
+
+#ifndef __AFXEXT_H__
+#include <afxext.h>
+#endif
+
+class T42View : public CFormView
+{
+protected:
+ T42View(); // protected constructor used by dynamic creation
+ DECLARE_DYNCREATE(T42View)
+
+// Form Data
+public:
+ static DWORD CALLBACK ESINProc(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG FAR *pcb);
+ void SystemMessage(LPCTSTR str);
+ void LoadLayout();
+ void SaveLayout();
+ void SetEnable(BOOL bEnable);
+ BOOL m_bEnabled;
+ HCURSOR m_hHorzCursor;
+ HCURSOR m_hVertCursor;
+ T42Frame* m_pFrame;
+ BOOL m_bTracking;
+ BOOL m_bShown;
+ enum _orientation {
+ ortHorizontal,
+ ortVertical
+ } m_Ort;
+ void RecalcLayout();
+ UINT m_gapSize;
+ UINT m_remoteSize;
+ UINT m_localSize;
+ CRemoteCtl m_remoteCtl;
+ CLocalCtl m_localCtl;
+ //{{AFX_DATA(T42View)
+ enum { IDD = IDD_T42VIEW };
+ CSplitBar m_splitCtl;
+ //}}AFX_DATA
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(T42View)
+ public:
+ virtual void OnInitialUpdate();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ virtual ~T42View();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+ // Generated message map functions
+ //{{AFX_MSG(T42View)
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg LRESULT OnSplitterBDown(WPARAM,LPARAM);
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
+ afx_msg void OnWindowSplitequally();
+ afx_msg void OnUpdateWindowHorizontalsplit(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateWindowVerticalsplit(CCmdUI* pCmdUI);
+ afx_msg void OnWindowHorizontalsplit();
+ afx_msg void OnWindowVerticalsplit();
+ afx_msg void OnEditCopy();
+ afx_msg void OnEditPaste();
+ afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);
+ afx_msg void OnCancelMode();
+ afx_msg void OnUpdateTeaSave(CCmdUI* pCmdUI);
+ afx_msg void OnTeaSave();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/help/T42.cnt b/help/T42.cnt
new file mode 100644
index 0000000..e30ddb8
--- a/dev/null
+++ b/help/T42.cnt
@@ -0,0 +1,16 @@
+:Base T42.hlp>Standard
+:Title T42
+1 T42
+2 About T42=About
+2 What's New=News
+2 Using T42=Using
+2 Options
+3 T42 Options=Options
+3 General Options=GeneralOptions
+3 Fonts=FontsOptions
+3 Sounds=SoundsOptions
+3 Secretary Options=SecretaryOptions
+2 Windows
+3 Main Window=MainWindow
+3 Conversation Window=ConversationWindow
+3 Announce Dialog=AnnounceDialog
diff --git a/help/T42.hpj b/help/T42.hpj
new file mode 100644
index 0000000..d7ad056
--- a/dev/null
+++ b/help/T42.hpj
@@ -0,0 +1,31 @@
+; This file is maintained by HCW. Do not modify this file directly.
+
+[OPTIONS]
+COMPRESS=12 Hall Zeck
+LCID=0x409 0x0 0x0 ; English (United States)
+REPORT=Yes
+TITLE=T42
+CNT=T42.cnt
+HLP=T42.HLP
+
+[FILES]
+T42.rtf
+
+[ALIAS]
+HIDD_ABOUTBOX=About
+HIDD_ANNOUNCE=AnnounceDialog
+HIDD_OPTIONS_FONTS=FontsOptions
+HIDD_OPTIONS_GENERAL=GeneralOptions
+HIDD_OPTIONS_SECRETARY=SecretaryOptions
+HIDD_OPTIONS_SOUNDS=SoundsOptions
+HIDD_REMOTE=RemoteDialog
+HIDD_T42_DIALOG=MainWindow
+HIDD_T42VIEW=ConversationWindow
+HIDR_MAINFRAME=MainWindow
+HIDR_T42FRAME=ConversationWindow
+
+[MAP]
+#include T42.hm
+
+[WINDOWS]
+Standard="",(1,1,698,940),20740,(r14876671),(r12632256),f2
diff --git a/help/T42.rtf b/help/T42.rtf
new file mode 100644
index 0000000..678738a
--- a/dev/null
+++ b/help/T42.rtf
@@ -0,0 +1,194 @@
+{\rtf1\ansi
+@{\footnote
+THIS FILE WAS AUTOMATICALLY GENERATED FROM XML DOCUMENT.
+DO NOT MODIFY THIS FILE DIRECTLY. EDIT XML DOCUMENT INSTEAD
+}
+{\fonttbl{\f0\froman Times New Roman;}{\f1\fswiss Arial;}{\f3\froman Symbol;}}{\colortbl;
+ \red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;
+ \red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;
+ \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;
+ \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
+
+\pard\plain\keepn
+#{\footnote About}
+${\footnote About T42}
+{ \f1\fs18\b\sb120 About {\b T42}}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 {\b T42} is our {\i Win32} implementation of {\b\cf6 unix}{\b\cf6 ntalk} protocol.
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 It features:\pard
+\par \fi0\li0 \bullet {\b Multihoming} - works properly on multihomed machines (ie. accepts connections/issues requests on all interfaces);
+\par \fi0\li0 \bullet {\b Your personal secretary} - technically speaking, something like answering machine;
+\par \fi0\li0 \bullet {\b Sleep function} - be notified of activities in backgrounded windows;\pard
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Designed to be compatible with our {\i TFTP} client/server, {\uldb {\b PumpKIN}}{\v %!ExecFile("http://www.klever.net/kin/pumpkin.html")}, that allows you to exchange files with your party while having talk sessions.
+\par\sa120\sb120\qj\pard \f1\fs18\sb120
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 {\b {\i Enjoy!}}
+{
+\par\pard\plain\sb360\sa120 \f1\fs16 Copyright (c) 1998, 2002 {\uldb\cf0 Klever Group (http://www.klever.net/)}{\v %!ExecFile("http://www.klever.net/")}
+\par\qj\sb120\sa120Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+\par The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+\par \sa360 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+}
+\par \sa0\sb120\ql \f1\fs16 Author: {\b\uldb\cf11 Michael Krelin ({\i hacker@klever.net})}{\v %!ExecFile("mailto:hacker@klever.net")}
+\par \sa0\sb0 Fan mail send to {\i\uldb gefilte@klever.net}{\v %!ExecFile("mailto:gefilte@klever.net")}
+\page
+
+\pard\plain
+#{\footnote News}
+${\footnote What's New}
+\par\pard\plain\f1\fs24\qc\cf2\b 1.5 - August 19th, 2002
+\par\pard\plain\fi0\li0\f1\fs18 \bullet Change of license and opening the source
+\page
+
+\pard\plain\keepn
+#{\footnote Using}
+${\footnote Using T42}
+{ \f1\fs18\b\sb120 Using {\b T42}}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Once you've installed {\b T42}, run it from {\i Programs/Accessories/Klever Co.} menu. A small cup icon will appear in the notification tray area.
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Left-click on the icon will get you to the {\uldb Main Window}{\v MainWindow}, right-click brings up the following menu:\pard
+\par \fi0\li0 \bullet {\b Order some tea} - Initiates talk session. This will open new {\uldb Conversation Window}{\v ConversationWindow} and prompt you for request details.
+\par \fi0\li0 \bullet {\b Away} - Toggle your away mode. It affects the way {\b T42} handles incoming calls. See {\uldb Main Window}{\v Mainwindow} for details.
+\par \fi0\li0 \bullet {\b Show Main Window} - Toggle visibility of the {\uldb Main Window}{\v MainWindow} from which you can control some of {\b T42} options and read/maintain your recorded messages.
+\par \fi0\li0 \bullet {\b Options} - Select this to bring up {\uldb Options dialog}{\v Options} so that you can customize {\b T42} to suit your needs.
+\par \fi0\li0 \bullet {\b Exit} - This is not likely to happen, but if you want to exit {\b T42} and unload it from memory - that's what {\b Exit} is for.\pard
+\page
+
+\pard\plain\keepn
+#{\footnote MainWindow}
+${\footnote Main Window}
+{ \f1\fs18\b\sb120 Main {\b T42} Window}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Main Window is a {\b T42} Control Center, it's exactly mouse-click away from most of {\b T42} functions. It consists of\pard
+\par \fi0\li0 \bullet {\b On Call} and {\b On Call when away} dropdown lists let you select the action to take when incoming call occurs in 'normal' and 'away' mode. Chose one of
+ \pard
+\par \fi0\li0 \bullet {\i Prompt} - Ask you what to do before taking any actions;
+\par \fi0\li0 \bullet {\i Secretary} - Relay incoming calls to your {\uldb personal secretary}{\v SecretaryOptions}. Some prefer to call it answering machine.
+\par \fi0\li0 \bullet {\i Not here} - Tell the caller you're not here ({\i not logged in}) and terminate connection.
+\par \fi0\li0 \bullet {\i Refuse} - Tell the caller you're not accepting messages and terminate connection.
+\par \fi0\li0 \bullet {\i Ignore} - Pretend that you didn't notice.\pard
+\par \fi0\li0 \bullet {\b Away} button toggles your away mode. When an incoming call occurs {\b T42} takes action based upon away mode and options selected in {\b On Call} and {\b On Call when away} dropdown lists.
+\par \fi0\li0 \bullet {\b Tea} button initiates new talk session. This will open new {\uldb Conversation Window}{\v ConversationWindow} and prompt you for {\uldb request details}{\v RemoteDialog}.
+\par \fi0\li0 \bullet {\b Options} button brings up {\uldb Configuration Dialog}{\v Options} that lets you customize {\b T42} according to your needs.
+\par \fi0\li0 \bullet {\b Exit} - button closes {\b T42} windows and removes {\b T42} from memory.
+\par \fi0\li0 \bullet {\b Help} button enters the help system. If you got this far, you probably don't need further explanations.
+\par \fi0\li0 \bullet {\b Recorded messages} list this is the list of messages recorded by your secretary. Messages are sorted by age, last ones first. Unanswered messages have a brighter cup icon unless you've explicitly marked the message as processed (see below for details). Right-click on the list entry presents you with popup menu from which you can:
+ \pard
+\par \fi0\li0 \bullet {\i Call back} the person who left the message. This is identical to initiating new talk session and entering caller's data manually. Note: if the caller has a dynamic IP address and have already disconnected from his ISP and reconnected back this may not work.
+\par \fi0\li0 \bullet {\i Delete} selected message(s). If you don't need recorded message anymore you can throw it away by selecting this.
+\par \fi0\li0 \bullet {\i Save to file..} menu option lets you save message into {\i RTF} file. Then you may print message text, import it into your {\b\cf6 MS Word} documents or do with it whatever you want.
+\par \fi0\li0 \bullet {\i Mark as new} message lets you force message state to 'unprocessed' which means that it will have brighter cup icon in front of it which is supposed to help you keep track of messages that you need to take care of.
+\par \fi0\li0 \bullet {\i Mark as processed} message is the reverse of {\i Mark as new} command.
+\par \fi0\li0 \bullet {\i Empty Log} simply removes all messages from the log.\pard
+\par \fi0\li0 \bullet {\b Message preview window} - the recorded message itself is shown in this window.\pard
+\page
+
+\pard\plain\keepn
+#{\footnote AnnounceDialog}
+${\footnote Announce Dialog}
+{ \f1\fs18\b\sb120 Announce Dialog Window}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 When incoming call occurs and you're set to get a prompt this dialog pops up. This dialog lets you chose what further actions you want {\b T42} to take and see the request details. The dialog looks like this:
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 \{bmct announce.bmp\}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Incoming call details are in {\b bold}. The details are:\pard
+\par \fi0\li0 \bullet {\b callee name} - this is your name, or what caller thinks it is. ({\i kamel} in this example)
+\par \fi0\li0 \bullet {\b tty} - terminal on which remote thinks you're logged on. This is not important for incoming requests. Normally this is only used on unix machines. ({\i tty0} in this example)
+\par \fi0\li0 \bullet {\b caller's name} - local username and hostname/IP address of caller. ({\i hacker@localhost} in this example)\pard
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Use {\b Yes, I'd appreciate some milk} button to answer the call and establish talk connection with caller, {\b Not now, have a cup of tea with secretary} to relay the call to your secretary and {\b No, thanks, I'm out to coffee house} to ignore call.
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 If you don't answer in 30 seconds the call is relayed to the secretary.
+\page
+
+\pard\plain\keepn
+#{\footnote Options}
+${\footnote Options}
+{ \f1\fs18\b\sb120 Options}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Options is a tabbed dialog box where you're supposed to change {\b T42} settings. It consists of\pard
+\par \fi0\li0 \bullet {\uldb General tab}{\v GeneralOptions} - tune general {\b T42} options. Not much to set there so far.
+\par \fi0\li0 \bullet {\uldb Format tab}{\v FontsOptions} - set up text formats (fonts, colors, etc.) for various windows.
+\par \fi0\li0 \bullet {\uldb Sounds tab}{\v SoundsOptions} - customize {\b T42} bells and whistles in this dialog.
+\par \fi0\li0 \bullet {\uldb Secretary tab}{\v SecretaryOptions} - teach your secretary manners here.\pard
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Note: you might need to restart {\b T42} for some options to take effect.
+\page
+
+\pard\plain\keepn
+#{\footnote GeneralOptions}
+${\footnote General Options}
+{ \f1\fs18\b\sb120 General Options}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Currently you can only set up talk port here. Talk port is the UDP> port {\b\cf6 talk daemon} listens for incoming connections at. You can enter either number of port or service name (as specified in your {\b services} file) here. Do not change this if you don't know what you're doing and don't understand the instructions above.
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Note: you have to restart {\b T42} for this option to take effect.
+\page
+
+\pard\plain\keepn
+#{\footnote FontsOptions}
+${\footnote Fonts Options}
+{ \f1\fs18\b\sb120 Fonts}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Set up various fonts for {\b T42} to use according to your own preferences. There are three formats for you to set:\pard
+\par \fi0\li0 \bullet {\b Local} - this is what your typing appears as.
+\par \fi0\li0 \bullet {\b Remote} - this is what your party's typing should look like.
+\par \fi0\li0 \bullet {\b System} - this is what system messages, like disconnection cause, etc. in talk windows look like.\pard
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 For each format you can set up {\b Font face}, {\b Font size}, {\b bold}, {\i italic}, {\ul underline}, {\strike strikeout} and {\b character set} to use. For some formats you can also set {\b foreground} and {\b background} colors.
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Note: these settings only affect new windows.
+\page
+
+\pard\plain\keepn
+#{\footnote SoundsOptions}
+${\footnote Sounds Options}
+{ \f1\fs18\b\sb120 Sounds}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 This is where you customize {\b T42} bells and whistles, specifically:\pard
+\par \fi0\li0 \bullet {\b Bell in {\b T42} window} - the sound to produce when you or your party sends ASCII BELL characters ({\b Ctrl-G}).
+\par \fi0\li0 \bullet {\b Prompt sound alert} the sound used to notify you of incoming call. You may also set {\b loop} for this sound to make it continuous for the {\uldb Announce Window}{\v AnnounceDialog} lifetime.
+\par \fi0\li0 \bullet {\b Wake-up sound alert} the sound used to let you know that {\b T42} leaves {\b sleep mode} (see {\uldb Conversation Window}{\v ConversationWindow} for details).\pard
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 For each sound you can either specify {\b .WAV} file (use browse button to choose it) or internal sound from drop-down list. You can also use play button to check what it sounds like.
+\page
+
+\pard\plain\keepn
+#{\footnote SecretaryOptions}
+${\footnote Secretary Options}
+{ \f1\fs18\b\sb120 Secretary}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 This is the place to teach your secretary how to behave. The things you can ask for are:\pard
+\par \fi0\li0 \bullet {\b Greeting message} - this is the message your secretary greets caller with. When greeting is transferred your secretary will automatically substitute time limit (see below) instead of {\b %t} and characters limit (see below) instead of {\b %c}.
+\par \fi0\li0 \bullet After greeting the caller your secretary will record the message until the caller will exceed either {\b time limit} or {\b character} limit. You may choose to disable either or both limits.
+\par \fi0\li0 \bullet You may also limit your secretary's ability to handle multiple calls to provide each caller with better service. Normally the optimal limit depends on your system resources and your callers' activities.\pard
+\page
+
+\pard\plain\keepn
+#{\footnote RemoteDialog}
+${\footnote Remote Dialog}
+{ \f1\fs18\b\sb120 Remote Dialog}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Whenever you want to issue talk request you're presented with a dialog in which you can enter your request details, it looks like this:
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 \{bmct invite.bmp\}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 The call details are:\pard
+\par \fi0\li0 \bullet {\i Callee address} - The address is in the form {\b user@host}, {\i kamel@192.168.168.192} in this example.
+\par \fi0\li0 \bullet {\i tty} - terminal line your party is logged on. It's only relevant when the callee is on unix system. If you don't know what to put in there - just leave it blank.
+\par \fi0\li0 \bullet {\i Your username} - this is how your call will appear to caller. Just don't leave it empty.\pard
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Note: your party address is {\b not} your party's email address, even if it looks similar. {\b host} part is either hostname your party logged in or {\b IP address} of the host. If your party has {\b dynamically assigned} IP address, one way to determine it is too look up in the headers of e-mail sent {\b after} your party's established internet connection last time (i.e. very recent one) and find something like
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 Received: from 209.203.65.22 (ppp22.kross.klever.net [209.203.65.22]) by mail.elsinore.klever.net (8.8.7/8.8.7) with SMTP id RAA15788
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 In this case the IP address would be {\b 209.203.65.22} and the host name {\b ppp22.kross.klever.net}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 So, you're advised to talk to {\b whoever@209.203.65.22} or {\b whoever@ppp22.kross.klever.net}. You don't need to worry if your party has a static IP address.
+\page
+
+\pard\plain\keepn
+#{\footnote ConversationWindow}
+${\footnote Conversation Window}
+{ \f1\fs18\b\sb120 Conversation Window}
+\par\sa120\sb120\qj\pard \f1\fs18\sb120 This is the window where actual conversation takes place. It is split into two panes for you and for your party. It is split either horizontal or vertical. In the former case you type in the upper half and see what your party does in the lower. In case of vertical orientation your part is the leftmost one. All control actions are done via menu bar. Here goes an explanation for each command:\pard
+\par \fi0\li0 \bullet {\b Tea}\pard
+\par \fi0\li0 \bullet {\i Remote user} - initiate talk session for this window. You will be prompted for {\uldb your party's whereabouts}{\v RemoteDialog}.
+\par \fi0\li0 \bullet {\i Close connection} - terminate talk session. This puts window into inactive state until you initiate new session.
+\par \fi0\li0 \bullet {\i Re-connect} - re-initiate talk session to the same party, for instance if you've lost connection.
+\par \fi0\li0 \bullet {\i Save} - if there was something important said you can save the whole conversation into RTF formatted file for future reference.
+\par \fi0\li0 \bullet {\i Exit} - will close conversation window and terminate the connection.\pard
+\par \fi0\li0 \bullet {\b Edit}\pard
+\par \fi0\li0 \bullet {\i Copy} - copy currently selected text into windows clipboard.
+\par \fi0\li0 \bullet {\i Paste} - paste window selection into your current conversation.\pard
+\par \fi0\li0 \bullet {\b Sleep}\pard
+\par \fi0\li0 \bullet {\i Sleep} - put your session to sleep. When your party shows some kind of activity {\b Wake-up action} will be taken (see below).
+\par \fi0\li0 \bullet {\i Sleep on minimize} - check this if you want to activate sleep mode whenever you minimize conversation window.
+\par \fi0\li0 \bullet {\i Minimize on sleep} - check this if you want to minimize window whenever you put it into sleep mode.
+\par \fi0\li0 \bullet {\i Wake-up action} - Actions to take whenever remote user shows activity in sleep mode. Possible actions are:
+ \pard
+\par \fi0\li0 \bullet Make sound - check this if you want {\b T42} to produce sound (as specified in {\uldb Sounds Options}{\v SoundsOptions}) whenever it leaves sleep mode.
+\par \fi0\li0 \bullet Pop-up - check this if you want {\b T42} to bring conversation window to foreground and restore if it is minimized whenever it leaves sleep mode.\pard\pard
+\par \fi0\li0 \bullet {\b Window}\pard
+\par \fi0\li0 \bullet {\i Split equally} split local and remote panes in equal propotions.
+\par \fi0\li0 \bullet {\i Save layout} - save window position, size and split proportions for future sessions.
+\par \fi0\li0 \bullet {\i Autosave layout} - automatically save layout whenever you close conversation window.
+\par \fi0\li0 \bullet {\i Horizontal split}/{\i Vertical split} - chose your orientation.
+\par \fi0\li0 \bullet {\i Hide on minimize} - set {\b T42} to hide window into notification tray icon whenever you minimize it.\pard\pard
+\page
+} \ No newline at end of file
diff --git a/help/T42.xml b/help/T42.xml
new file mode 100644
index 0000000..d59c255
--- a/dev/null
+++ b/help/T42.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0"?>
+<winhelp>
+ <topic id="About" title="About T42">
+ <heading scroll="no">About <kin>T42</kin></heading>
+ <p><kin>T42</kin> is our <term>Win32</term> implementation of <product>unix</product> <product>ntalk</product> protocol.</p>
+ <p>It features:</p>
+ <ul>
+ <li><b>Multihoming</b> - works properly on multihomed machines (ie. accepts connections/issues requests on all interfaces);</li>
+ <li><b>Your personal secretary</b> - technically speaking, something like answering machine;</li>
+ <li><b>Sleep function</b> - be notified of activities in backgrounded windows;</li>
+ </ul>
+ <p>Designed to be compatible with our <term>TFTP</term> client/server, <kin href="http://www.klever.net/kin/pumpkin.html">PumpKIN</kin>, that allows you to exchange files with your party while having talk sessions.</p>
+ <p/>
+ <p><b><i>Enjoy!</i></b></p>
+ <license years="1998, 2002"/>
+ <credits/>
+ </topic>
+ <topic id="News" title="What's New">
+ <newsfor version="1.5" date="August 19th, 2002">
+ <ni>Change of license and opening the source</ni>
+ </newsfor>
+ </topic>
+ <topic id="Using" title="Using T42">
+ <heading scroll="no">Using <kin>T42</kin></heading>
+ <p>Once you've installed <kin>T42</kin>, run it from <i>Programs/Accessories/Klever Co.</i> menu. A small cup icon will appear in the notification tray area.</p>
+ <p>Left-click on the icon will get you to the <a href="#MainWindow">Main Window</a>, right-click brings up the following menu:</p>
+ <ul>
+ <li><b>Order some tea</b> - Initiates talk session. This will open new <a href="#ConversationWindow">Conversation Window</a> and prompt you for request details.</li>
+ <li><b>Away</b> - Toggle your away mode. It affects the way <kin>T42</kin> handles incoming calls. See <a href="#Mainwindow">Main Window</a> for details.</li>
+ <li><b>Show Main Window</b> - Toggle visibility of the <a href="#MainWindow">Main Window</a> from which you can control some of <kin>T42</kin> options and read/maintain your recorded messages.</li>
+ <li><b>Options</b> - Select this to bring up <a href="#Options">Options dialog</a> so that you can customize <kin>T42</kin> to suit your needs.</li>
+ <li><b>Exit</b> - This is not likely to happen, but if you want to exit <kin>T42</kin> and unload it from memory - that's what <b>Exit</b> is for.</li>
+ </ul>
+ </topic>
+ <topic id="MainWindow" title="Main Window">
+ <heading scroll="no">Main <kin>T42</kin> Window</heading>
+ <p>Main Window is a <kin>T42</kin> Control Center, it's exactly mouse-click away from most of <kin>T42</kin> functions. It consists of</p>
+ <ul>
+ <li><b>On Call</b> and <b>On Call when away</b> dropdown lists let you select the action to take when incoming call occurs in 'normal' and 'away' mode. Chose one of
+ <ul>
+ <li><i>Prompt</i> - Ask you what to do before taking any actions;</li>
+ <li><i>Secretary</i> - Relay incoming calls to your <a href="#SecretaryOptions">personal secretary</a>. Some prefer to call it answering machine.</li>
+ <li><i>Not here</i> - Tell the caller you're not here (<i>not logged in</i>) and terminate connection.</li>
+ <li><i>Refuse</i> - Tell the caller you're not accepting messages and terminate connection.</li>
+ <li><i>Ignore</i> - Pretend that you didn't notice.</li>
+ </ul>
+ </li>
+ <li><b>Away</b> button toggles your away mode. When an incoming call occurs <kin>T42</kin> takes action based upon away mode and options selected in <b>On Call</b> and <b>On Call when away</b> dropdown lists.</li>
+ <li><b>Tea</b> button initiates new talk session. This will open new <a href="#ConversationWindow">Conversation Window</a> and prompt you for <a href="#RemoteDialog">request details</a>.</li>
+ <li><b>Options</b> button brings up <a href="#Options">Configuration Dialog</a> that lets you customize <kin>T42</kin> according to your needs.</li>
+ <li><b>Exit</b> - button closes <kin>T42</kin> windows and removes <kin>T42</kin> from memory.</li>
+ <li><b>Help</b> button enters the help system. If you got this far, you probably don't need further explanations.</li>
+ <li><b>Recorded messages</b> list this is the list of messages recorded by your secretary. Messages are sorted by age, last ones first. Unanswered messages have a brighter cup icon unless you've explicitly marked the message as processed (see below for details). Right-click on the list entry presents you with popup menu from which you can:
+ <ul>
+ <li><i>Call back</i> the person who left the message. This is identical to initiating new talk session and entering caller's data manually. Note: if the caller has a dynamic IP address and have already disconnected from his ISP and reconnected back this may not work.</li>
+ <li><i>Delete</i> selected message(s). If you don't need recorded message anymore you can throw it away by selecting this.</li>
+ <li><i>Save to file..</i> menu option lets you save message into <term>RTF</term> file. Then you may print message text, import it into your <product>MS Word</product> documents or do with it whatever you want.</li>
+ <li><i>Mark as new</i> message lets you force message state to 'unprocessed' which means that it will have brighter cup icon in front of it which is supposed to help you keep track of messages that you need to take care of.</li>
+ <li><i>Mark as processed</i> message is the reverse of <i>Mark as new</i> command.</li>
+ <li><i>Empty Log</i> simply removes all messages from the log.</li>
+ </ul>
+ </li>
+ <li><b>Message preview window</b> - the recorded message itself is shown in this window.</li>
+ </ul>
+ </topic>
+ <topic id="AnnounceDialog" title="Announce Dialog">
+ <heading scroll="no">Announce Dialog Window</heading>
+ <p>When incoming call occurs and you're set to get a prompt this dialog pops up. This dialog lets you chose what further actions you want <kin>T42</kin> to take and see the request details. The dialog looks like this:</p>
+ <p><image source="announce.bmp"/></p>
+ <p>Incoming call details are in <b>bold</b>. The details are:</p>
+ <ul>
+ <li><b>callee name</b> - this is your name, or what caller thinks it is. (<i>kamel</i> in this example)</li>
+ <li><b>tty</b> - terminal on which remote thinks you're logged on. This is not important for incoming requests. Normally this is only used on unix machines. (<i>tty0</i> in this example)</li>
+ <li><b>caller's name</b> - local username and hostname/IP address of caller. (<i>hacker@localhost</i> in this example)</li>
+ </ul>
+ <p>Use <b>Yes, I'd appreciate some milk</b> button to answer the call and establish talk connection with caller, <b>Not now, have a cup of tea with secretary</b> to relay the call to your secretary and <b>No, thanks, I'm out to coffee house</b> to ignore call.</p>
+ <p>If you don't answer in 30 seconds the call is relayed to the secretary.</p>
+ </topic>
+ <topic id="Options" title="Options">
+ <heading scroll="no">Options</heading>
+ <p>Options is a tabbed dialog box where you're supposed to change <kin>T42</kin> settings. It consists of</p>
+ <ul>
+ <li><a href="#GeneralOptions">General tab</a> - tune general <kin>T42</kin> options. Not much to set there so far.</li>
+ <li><a href="#FontsOptions">Format tab</a> - set up text formats (fonts, colors, etc.) for various windows.</li>
+ <li><a href="#SoundsOptions">Sounds tab</a> - customize <kin>T42</kin> bells and whistles in this dialog.</li>
+ <li><a href="#SecretaryOptions">Secretary tab</a> - teach your secretary manners here.</li>
+ </ul>
+ <p>Note: you might need to restart <kin>T42</kin> for some options to take effect.</p>
+ </topic>
+ <topic id="GeneralOptions" title="General Options">
+ <heading scroll="no">General Options</heading>
+ <p>Currently you can only set up talk port here. Talk port is the UDP> port <product>talk daemon</product> listens for incoming connections at. You can enter either number of port or service name (as specified in your <b>services</b> file) here. Do not change this if you don't know what you're doing and don't understand the instructions above.</p>
+ <p>Note: you have to restart <kin>T42</kin> for this option to take effect.</p>
+ </topic>
+ <topic id="FontsOptions" title="Fonts Options">
+ <heading scroll="no">Fonts</heading>
+ <p>Set up various fonts for <kin>T42</kin> to use according to your own preferences. There are three formats for you to set:</p>
+ <ul>
+ <li><b>Local</b> - this is what your typing appears as.</li>
+ <li><b>Remote</b> - this is what your party's typing should look like.</li>
+ <li><b>System</b> - this is what system messages, like disconnection cause, etc. in talk windows look like.</li>
+ </ul>
+ <p>For each format you can set up <b>Font face</b>, <b>Font size</b>, <b>bold</b>, <i>italic</i>, <u>underline</u>, <strike>strikeout</strike> and <b>character set</b> to use. For some formats you can also set <b>foreground</b> and <b>background</b> colors.</p>
+ <p>Note: these settings only affect new windows.</p>
+ </topic>
+ <topic id="SoundsOptions" title="Sounds Options">
+ <heading scroll="no">Sounds</heading>
+ <p>This is where you customize <kin>T42</kin> bells and whistles, specifically:</p>
+ <ul>
+ <li><b>Bell in <kin>T42</kin> window</b> - the sound to produce when you or your party sends ASCII BELL characters (<b>Ctrl-G</b>).</li>
+ <li><b>Prompt sound alert</b> the sound used to notify you of incoming call. You may also set <b>loop</b> for this sound to make it continuous for the <a href="#AnnounceDialog">Announce Window</a> lifetime.</li>
+ <li><b>Wake-up sound alert</b> the sound used to let you know that <kin>T42</kin> leaves <b>sleep mode</b> (see <a href="#ConversationWindow">Conversation Window</a> for details).</li>
+ </ul>
+ <p>For each sound you can either specify <b>.WAV</b> file (use browse button to choose it) or internal sound from drop-down list. You can also use play button to check what it sounds like.</p>
+ </topic>
+ <topic id="SecretaryOptions" title="Secretary Options">
+ <heading scroll="no">Secretary</heading>
+ <p>This is the place to teach your secretary how to behave. The things you can ask for are:</p>
+ <ul>
+ <li><b>Greeting message</b> - this is the message your secretary greets caller with. When greeting is transferred your secretary will automatically substitute time limit (see below) instead of <b>%t</b> and characters limit (see below) instead of <b>%c</b>.</li>
+ <li>After greeting the caller your secretary will record the message until the caller will exceed either <b>time limit</b> or <b>character</b> limit. You may choose to disable either or both limits.</li>
+ <li>You may also limit your secretary's ability to handle multiple calls to provide each caller with better service. Normally the optimal limit depends on your system resources and your callers' activities.</li>
+ </ul>
+ </topic>
+ <topic id="RemoteDialog" title="Remote Dialog">
+ <heading scroll="no">Remote Dialog</heading>
+ <p>Whenever you want to issue talk request you're presented with a dialog in which you can enter your request details, it looks like this:</p>
+ <p><image source="invite.bmp"/></p>
+ <p>The call details are:</p>
+ <ul>
+ <li><i>Callee address</i> - The address is in the form <b>user@host</b>, <i>kamel@192.168.168.192</i> in this example.</li>
+ <li><i>tty</i> - terminal line your party is logged on. It's only relevant when the callee is on unix system. If you don't know what to put in there - just leave it blank.</li>
+ <li><i>Your username</i> - this is how your call will appear to caller. Just don't leave it empty.</li>
+ </ul>
+ <p>Note: your party address is <b>not</b> your party's email address, even if it looks similar. <b>host</b> part is either hostname your party logged in or <b>IP address</b> of the host. If your party has <b>dynamically assigned</b> IP address, one way to determine it is too look up in the headers of e-mail sent <b>after</b> your party's established internet connection last time (i.e. very recent one) and find something like</p>
+ <p>Received: from 209.203.65.22 (ppp22.kross.klever.net [209.203.65.22]) by mail.elsinore.klever.net (8.8.7/8.8.7) with SMTP id RAA15788</p>
+ <p>In this case the IP address would be <b>209.203.65.22</b> and the host name <b>ppp22.kross.klever.net</b></p>
+ <p>So, you're advised to talk to <b>whoever@209.203.65.22</b> or <b>whoever@ppp22.kross.klever.net</b>. You don't need to worry if your party has a static IP address.</p>
+ </topic>
+ <topic id="ConversationWindow" title="Conversation Window">
+ <heading scroll="no">Conversation Window</heading>
+ <p>This is the window where actual conversation takes place. It is split into two panes for you and for your party. It is split either horizontal or vertical. In the former case you type in the upper half and see what your party does in the lower. In case of vertical orientation your part is the leftmost one. All control actions are done via menu bar. Here goes an explanation for each command:</p>
+ <ul>
+ <li><b>Tea</b>
+ <ul>
+ <li><i>Remote user</i> - initiate talk session for this window. You will be prompted for <a href="#RemoteDialog">your party's whereabouts</a>.</li>
+ <li><i>Close connection</i> - terminate talk session. This puts window into inactive state until you initiate new session.</li>
+ <li><i>Re-connect</i> - re-initiate talk session to the same party, for instance if you've lost connection.</li>
+ <li><i>Save</i> - if there was something important said you can save the whole conversation into RTF formatted file for future reference.</li>
+ <li><i>Exit</i> - will close conversation window and terminate the connection.</li>
+ </ul>
+ </li>
+ <li><b>Edit</b>
+ <ul>
+ <li><i>Copy</i> - copy currently selected text into windows clipboard.</li>
+ <li><i>Paste</i> - paste window selection into your current conversation.</li>
+ </ul>
+ </li>
+ <li><b>Sleep</b>
+ <ul>
+ <li><i>Sleep</i> - put your session to sleep. When your party shows some kind of activity <b>Wake-up action</b> will be taken (see below).</li>
+ <li><i>Sleep on minimize</i> - check this if you want to activate sleep mode whenever you minimize conversation window.</li>
+ <li><i>Minimize on sleep</i> - check this if you want to minimize window whenever you put it into sleep mode.</li>
+ <li><i>Wake-up action</i> - Actions to take whenever remote user shows activity in sleep mode. Possible actions are:
+ <ul>
+ <li>Make sound - check this if you want <kin>T42</kin> to produce sound (as specified in <a href="#SoundsOptions">Sounds Options</a>) whenever it leaves sleep mode.</li>
+ <li>Pop-up - check this if you want <kin>T42</kin> to bring conversation window to foreground and restore if it is minimized whenever it leaves sleep mode.</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li><b>Window</b>
+ <ul>
+ <li><i>Split equally</i> split local and remote panes in equal propotions.</li>
+ <li><i>Save layout</i> - save window position, size and split proportions for future sessions.</li>
+ <li><i>Autosave layout</i> - automatically save layout whenever you close conversation window.</li>
+ <li><i>Horizontal split</i>/<i>Vertical split</i> - chose your orientation.</li>
+ <li><i>Hide on minimize</i> - set <kin>T42</kin> to hide window into notification tray icon whenever you minimize it.</li>
+ </ul>
+ </li>
+ </ul>
+ </topic>
+</winhelp>
diff --git a/help/announce.bmp b/help/announce.bmp
new file mode 100644
index 0000000..5c40627
--- a/dev/null
+++ b/help/announce.bmp
Binary files differ
diff --git a/help/invite.bmp b/help/invite.bmp
new file mode 100644
index 0000000..7dac6bb
--- a/dev/null
+++ b/help/invite.bmp
Binary files differ
diff --git a/install/custom.rch b/install/custom.rch
new file mode 100644
index 0000000..8916c47
--- a/dev/null
+++ b/install/custom.rch
@@ -0,0 +1,10 @@
+#ifdef STATI_K
+T42.ex_ rcdata discardable "../releast/T42.ex_"
+#else
+T42.ex_ rcdata discardable "../release/T42.ex_"
+#endif
+T42.cn_ rcdata discardable "../release/T42.cn_"
+T42.hl_ rcdata discardable "../release/T42.hl_"
+#ifdef K_ANNED
+mfc42.dl_ rcdata discardable "../redist/mfc42.dl_"
+#endif
diff --git a/install/install.cpp b/install/install.cpp
new file mode 100644
index 0000000..89eb3fc
--- a/dev/null
+++ b/install/install.cpp
@@ -0,0 +1,68 @@
+#include "resource.h"
+#include "../shared-code/install.h"
+
+#define KINAME "T42 1.5"
+#define SKINAME "T42"
+
+BOOL Install(void)
+{
+STRING dPath = strFETCH_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.",SKINAME "Path");
+STRING kPath = strFETCH_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.","KINPath");
+LPCSTR qPath = ((LPCSTR)dPath)?(LPCSTR)dPath:(((LPCSTR)kPath)?(LPSTR)kPath:"C:\\Program Files\\Klever\\Nothings");
+STRING path = REQUESTPATH(" " KINAME,"\nEnter destination path:",qPath);
+ if(!path)
+ return NULL;
+
+#ifdef K_ANNED
+STRING sysDir(_MAX_PATH);
+ GetSystemDirectory(sysDir,_MAX_PATH);
+ INSTALLFILE("mfc42.dl_",sysDir,"mfc42.dll");
+#endif
+
+ MAKE_PATH(path);
+STRING shortPath = GET_SHORT_PATH(path);
+ if(!shortPath){
+ MessageBox(NULL,"Failed to install " KINAME " in specified directory",NULL,MB_ICONERROR|MB_OK);
+ return FALSE;
+ }
+
+ if(!(
+ INSTALLFILE(SKINAME ".ex_",path,SKINAME ".exe") &&
+ INSTALLFILE(SKINAME ".hl_",path,SKINAME ".hlp") &&
+ INSTALLFILE(SKINAME ".cn_",path,SKINAME ".cnt")
+ )){
+ MessageBox(NULL,"Failed to install " KINAME " in specified directory",NULL,MB_ICONERROR|MB_OK);
+ return FALSE;
+ }
+ ADDMENU("Accessories\\Klever Co.",SKINAME,path, SKINAME ".exe");
+
+ strSET_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.",SKINAME "Path",path);
+ strSET_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.","KINPath",path);
+
+FILE* inf=CREATE_INF_FILE(path,SKINAME ".INF");
+ if(!inf){
+ MessageBox(NULL,"Failed to install " KINAME,NULL,MB_ICONERROR|MB_OK);
+ return FALSE;
+ }
+ INF_FILE_HEADER(inf);
+ INF_FILE_SECTION(inf,"Uninstall");
+ fprintf(inf,"AddReg=kFiles\nDelReg=kReg\nUpdateInis=kMenu\n");
+ INF_FILE_SECTION(inf,"kFiles");
+ INF_REMOVE_ROOT(inf,SKINAME "Files",shortPath);
+ INF_REMOVE_FILE(inf,SKINAME "Files",SKINAME ".exe");
+ INF_REMOVE_HELP_FILE(inf,SKINAME "Files",SKINAME);
+ INF_REMOVE_FILE(inf,SKINAME "Files",SKINAME ".inf");
+ INF_REMOVE_FILE(inf,SKINAME "Files",SKINAME ".Calls");
+ INF_FILE_SECTION(inf,"kReg");
+ INF_UNINSTALL_REG(inf,SKINAME);
+ INF_FILE_SECTION(inf,"kMenu");
+ INF_MENU_GROUP(inf,1,"Accessories\\Klever Co.");
+ INF_MENU_ITEM(inf,1,SKINAME);
+ fclose(inf);
+
+ REG_UNINSTALL_COMMAND(SKINAME,"Klever " KINAME,shortPath,SKINAME ".INF","Uninstall");
+
+ MessageBox(NULL,KINAME " installed successfully, you may now run it from Programs/Accessories/Klever Co. menu or remove it using Control Panel Add/Remove Programs applet."," Rejoice!",MB_ICONINFORMATION|MB_OK);
+
+ return TRUE;
+}
diff --git a/install/install.rc b/install/install.rc
new file mode 100644
index 0000000..a613be0
--- a/dev/null
+++ b/install/install.rc
@@ -0,0 +1,182 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+#if defined(APSTUDIO_INVOKED) || defined(FALSE)
+#if defined(APSTUDIO_INVOKED)
+IDD_INSTALLING$(FALSE) DIALOGEX 0, 0, 200, 74
+#else
+IDD_INSTALLING DIALOGEX 0, 0, 200, 74
+#endif
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ PUSHBUTTON "Cancel",IDCANCEL,143,53,50,14,BS_CENTER | BS_VCENTER |
+ BS_NOTIFY | BS_FLAT,WS_EX_DLGMODALFRAME
+ CONTROL "Animate1",IDC_DISKS,"SysAnimate32",ACS_TRANSPARENT |
+ ACS_AUTOPLAY | WS_TABSTOP,161,7,32,32
+ LTEXT "",IDC_STATE,7,7,150,32,SS_NOPREFIX | SS_NOTIFY
+ CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",0x0,7,45,
+ 186,7,WS_EX_DLGMODALFRAME
+END
+#endif
+
+IDD_PATH DIALOGEX 0, 0, 255, 73
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "",IDC_PROMPT,7,7,241,30
+ EDITTEXT IDC_PATH,7,37,195,12,ES_AUTOHSCROLL
+ PUSHBUTTON "B&rowse..",IDC_BROWSE,208,37,40,12
+ DEFPUSHBUTTON "OK",IDOK,69,52,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,135,52,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ "IDD_INSTALLING$(FALSE)", DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 193
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 67
+ HORZGUIDE, 39
+ END
+
+ IDD_PATH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 248
+ VERTGUIDE, 202
+ VERTGUIDE, 208
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 66
+ HORZGUIDE, 37
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""custom.rch""\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON ICON DISCARDABLE "../shared-data/install-icon.ico"
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,5,0,0
+ PRODUCTVERSION 1,5,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Klever Group (http://www.klever.net/)\0"
+ VALUE "FileDescription", "INSTALL: T42, unix talk/ntalk implementation\0"
+ VALUE "FileVersion", "1, 5, 0, 0\0"
+ VALUE "InternalName", "INSTALL\0"
+ VALUE "LegalCopyright", "Copyright © 1998, 2002 Klever Group (http://www.klever.net/)\0"
+ VALUE "LegalTrademarks", "Klever Group (http://www.klever.net/)\0"
+ VALUE "OriginalFilename", "INSTALL.EXE\0"
+ VALUE "ProductName", "T42\0"
+ VALUE "ProductVersion", "1, 5, 0, 0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "custom.rch"
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/install/resource.h b/install/resource.h
new file mode 100644
index 0000000..ebf7991
--- a/dev/null
+++ b/install/resource.h
@@ -0,0 +1,24 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Install.rc
+//
+#define IDD_INSTALLING 101
+#define IDD_PATH 102
+#define IDI_ICON 105
+#define IDC_DISKS 1000
+#define IDC_STATE 1001
+#define IDC_PROGRESS 1002
+#define IDC_PROMPT 1003
+#define IDC_PATH 1004
+#define IDC_BROWSE 1005
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1006
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/makehelp.bat b/makehelp.bat
new file mode 100644
index 0000000..961dba0
--- a/dev/null
+++ b/makehelp.bat
@@ -0,0 +1,34 @@
+@echo off
+REM -- First make map file from Microsoft Visual C++ generated resource.h
+echo // MAKEHELP.BAT generated Help Map file. Used by T42.HPJ. >"help\T42.hm"
+echo. >>"help\T42.hm"
+echo // Commands (ID_* and IDM_*) >>"help\T42.hm"
+makehm ID_,HID_,0x10000 IDM_,HIDM_,0x10000 resource.h >>"help\T42.hm"
+echo. >>"help\T42.hm"
+echo // Prompts (IDP_*) >>"help\T42.hm"
+makehm IDP_,HIDP_,0x30000 resource.h >>"help\T42.hm"
+echo. >>"help\T42.hm"
+echo // Resources (IDR_*) >>"help\T42.hm"
+makehm IDR_,HIDR_,0x20000 resource.h >>"help\T42.hm"
+echo. >>"help\T42.hm"
+echo // Dialogs (IDD_*) >>"help\T42.hm"
+makehm IDD_,HIDD_,0x20000 resource.h >>"help\T42.hm"
+echo. >>"help\T42.hm"
+echo // Frame Controls (IDW_*) >>"help\T42.hm"
+makehm IDW_,HIDW_,0x50000 resource.h >>"help\T42.hm"
+REM -- Make help for Project T42
+
+echo Building RTF file
+xsltproc -o help/T42.rtf shared-code/kinhelp.xsl help/T42.xml
+echo Building Win32 Help files
+start /wait hcrtf -x "help\T42.hpj"
+echo.
+if exist Debug\nul copy "help\T42.hlp" Debug
+if exist Debug\nul copy "help\T42.cnt" Debug
+if exist Release\nul copy "help\T42.hlp" Release
+if exist Release\nul copy "help\T42.cnt" Release
+if exist Releast\nul copy "help\T42.hlp" Releast
+if exist Releast\nul copy "help\T42.cnt" Releast
+echo.
+
+
diff --git a/res/IDR_FLIP.ico b/res/IDR_FLIP.ico
new file mode 100644
index 0000000..96f5037
--- a/dev/null
+++ b/res/IDR_FLIP.ico
Binary files differ
diff --git a/res/IDR_FULL.ico b/res/IDR_FULL.ico
new file mode 100644
index 0000000..bab7f6b
--- a/dev/null
+++ b/res/IDR_FULL.ico
Binary files differ
diff --git a/res/IDR_T42F.ico b/res/IDR_T42F.ico
new file mode 100644
index 0000000..9ac57dd
--- a/dev/null
+++ b/res/IDR_T42F.ico
Binary files differ
diff --git a/res/T42-beep.wav b/res/T42-beep.wav
new file mode 100644
index 0000000..40d0baa
--- a/dev/null
+++ b/res/T42-beep.wav
Binary files differ
diff --git a/res/T42-boiling.wav b/res/T42-boiling.wav
new file mode 100644
index 0000000..857c5b2
--- a/dev/null
+++ b/res/T42-boiling.wav
Binary files differ
diff --git a/res/T42-whistle.wav b/res/T42-whistle.wav
new file mode 100644
index 0000000..1ad9e77
--- a/dev/null
+++ b/res/T42-whistle.wav
Binary files differ
diff --git a/res/T42.ico b/res/T42.ico
new file mode 100644
index 0000000..1f3b80c
--- a/dev/null
+++ b/res/T42.ico
Binary files differ
diff --git a/res/T42.rc2 b/res/T42.rc2
new file mode 100644
index 0000000..415b466
--- a/dev/null
+++ b/res/T42.rc2
@@ -0,0 +1,13 @@
+//
+// T42.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/res/T42calln.ico b/res/T42calln.ico
new file mode 100644
index 0000000..e88ee61
--- a/dev/null
+++ b/res/T42calln.ico
Binary files differ
diff --git a/res/T42callp.ico b/res/T42callp.ico
new file mode 100644
index 0000000..5679c09
--- a/dev/null
+++ b/res/T42callp.ico
Binary files differ
diff --git a/res/fullcup.ico b/res/fullcup.ico
new file mode 100644
index 0000000..2e41084
--- a/dev/null
+++ b/res/fullcup.ico
Binary files differ
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..5292c49
--- a/dev/null
+++ b/resource.h
@@ -0,0 +1,200 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by T42.rc
+//
+#define IDM_ABOUTBOX 0x0010
+#define IDD_ABOUTBOX 100
+#define IDS_ABOUTBOX 101
+#define IDD_T42VIEW 101
+#define IDD_T42_DIALOG 102
+#define IDS_ERR_MALFORMEDREMOTE 102
+#define IDP_SOCKETS_INIT_FAILED 103
+#define ID_INDICATOR_DATE 104
+#define IDS_STATUS_RESOLVING 105
+#define IDC_TRAYICON 105
+#define IDS_ERR_REMOTERESOLVEFAILED 106
+#define IDD_OPTIONS_SOUNDS 106
+#define IDS_ERR_CTLCREATEFAILED 107
+#define IDS_ERR_CTLBINDFAILED 108
+#define IDS_ERR_CTLGETFAILED 109
+#define IDS_ERR_TCPCREATEFAILED 110
+#define IDS_ERR_TCPBINDFAILED 111
+#define IDS_ERR_TCPGETFAILED 112
+#define IDS_STATUS_LOOKUPINVITE 113
+#define IDS_ERR_TCPASELFAILED 114
+#define IDS_STATUS_WAITINGTOCONNECT 115
+#define IDS_ERR_TCPCONNECTFAILED 116
+#define IDS_ERR_TCPLISTENFAILED 117
+#define IDS_ERR_LTNASELFAILED 118
+#define IDS_ERR_CTLLOOKUPFAILED 119
+#define IDS_ERR_ANNOUNCEFAILURE 120
+#define IDS_CTL_NOTHERE 121
+#define IDS_CTL_FAILED 122
+#define IDS_CTL_MACHUNKNOWN 123
+#define IDS_CTL_PERMISSIONDENIED 124
+#define IDS_CTL_BADREQUEST 125
+#define IDS_CTL_BADVERSION 126
+#define IDS_CTL_BADADDR 127
+#define IDR_MAINFRAME 128
+#define IDS_CTL_BADCTL 128
+#define IDR_T42FRAME 129
+#define IDS_CTL_UNKNOWNERROR 130
+#define IDI_FULLCUP 130
+#define IDS_ERR_ANNOUNCEFAILED 131
+#define IDR_FULLT42 131
+#define IDD_REMOTE 132
+#define IDS_ERR_LEAVINVITEFAILED 132
+#define IDS_ERR_TCPACCEPTFAILED 133
+#define IDS_STATUS_ANNOUNCING 134
+#define IDD_ANNOUNCE 135
+#define IDS_ERR_CTLLDELETEFAILED 135
+#define IDS_ERR_CTLRDELETEFAILED 136
+#define IDD_OPTIONS_FONTS 136
+#define IDS_ERR_TCPERROR 137
+#define IDB_BACK 137
+#define IDD_OPTIONS_SECRETARY 137
+#define IDS_STATUS_ESTABLISHED 138
+#define IDD_OPTIONS_GENERAL 138
+#define IDS_STATUS_CONNECTIONCLOSED 139
+#define IDM_POPUPS 139
+#define IDW_BEEP_DROP 140
+#define IDS_TITLE_TEAWITH 140
+#define IDW_ANNOUNCE_BOILING 141
+#define IDS_TITLE_TEAFORTWO 141
+#define IDW_WAKE_WHISTLE 142
+#define IDS_TITLE_OPTIONS 142
+#define IDS_SND_TEADROP 143
+#define IDS_SND_BOILINGTEAPOT 144
+#define IDI_BROWSE 145
+#define IDS_SND_TEAPOTWHISTLE 145
+#define IDS_TITLE_WAV 146
+#define IDI_T42CALLNEW 146
+#define IDS_FILTER_WAV 147
+#define IDI_T42CALLPROCESSED 147
+#define IDS_FMT_T42LOCAL 148
+#define IDR_FLIPPEDCUP 148
+#define IDS_FMT_T42REMOTE 149
+#define IDS_FMT_T42SYSTEM 150
+#define IDI_PREPLAY 150
+#define IDS_CHARSET_AUTO 151
+#define IDS_DEFAULTGREETING 152
+#define IDS_DEFAULTPARTING 153
+#define IDS_FILENAME_T42 153
+#define IDS_FORMAT_TIME 154
+#define IDS_RTF_HEAD 154
+#define IDS_FILE_T42CALLS 155
+#define IDS_FORMAT_CALLTIME 156
+#define IDS_FILTER_RTF 157
+#define IDS_FORMAT_CALLDURATION 158
+#define IDS_FORMAT_CALLTIMELONG 159
+#define IDS_FORMAT_T42CALLHEADER 160
+#define IDS_WSA_ENETDOWN 161
+#define IDS_WSA_ECONNRESET 162
+#define IDS_WSA_ECONNABORTED 163
+#define IDS_WSA_ECONNREFUSED 164
+#define IDS_WSA_ENETUNREACH 165
+#define IDS_WSA_ETIMEDOUT 166
+#define IDS_CONNECTIONCLOSED 167
+#define IDS_WSA_NODATA 168
+#define IDS_ERR_CONNECTIONCLOSED 169
+#define IDS_WSA_HOSTNOTFOUND 170
+#define IDS_KLEVERNET_URL 171
+#define IDS_RTF_DELIMITER 172
+#define IDS_RTF_TAIL 173
+#define IDS_FAILVALIDATE_NTALKPORT 174
+#define IDS_CALLOG_OPEN_FAILED 175
+#define IDS_CALLOG_CLOSE_FAILED 176
+#define IDS_DAEMON_FAIL 177
+#define IDS_REGISTRYKEY 178
+#define IDS_DEFAULTCALLER 179
+#define IDC_CALLEE 1000
+#define IDC_TALK 1001
+#define IDC_OPTIONS 1002
+#define IDC_SPLIT 1005
+#define IDC_CALLER 1006
+#define IDC_TTY 1008
+#define IDC_SECRETARY 1009
+#define IDC_PREVIEW 1011
+#define IDC_CALLS 1012
+#define IDC_ONCALL 1015
+#define IDC_T42BELL_BROWSE 1016
+#define IDC_ONCALLAWAY 1016
+#define IDC_T42BELL 1017
+#define IDC_T42PROMPT 1018
+#define IDC_T42PROMPT_BROWSE 1019
+#define IDC_T42PROMPT_LOOP 1020
+#define IDC_T42WAKE 1021
+#define IDC_T42WAKE_BROWSE 1022
+#define IDC_SAMPLE 1023
+#define IDC_T42BELL_PLAY 1023
+#define IDC_FORMATNAME 1024
+#define IDC_T42PROMPT_PLAY 1024
+#define IDC_FACES 1025
+#define IDC_T42WAKE_PLAY 1025
+#define IDC_FONTSIZE 1026
+#define IDC_FORECOLOR 1027
+#define IDC_BACKCOLOR 1028
+#define IDC_BOLD 1029
+#define IDC_ITALIC 1030
+#define IDC_CHARSET 1031
+#define IDC_UNDERLINE 1032
+#define IDC_STRIKEOUT 1033
+#define IDC_TIP 1034
+#define IDC_GREETING 1035
+#define IDC_DOBYTELIMIT 1038
+#define IDC_BYTELIMIT 1039
+#define IDC_DOTIMELIMIT 1040
+#define IDC_TIMELIMIT 1041
+#define IDC_PARTING 1042
+#define IDC_WINLIMIT 1042
+#define IDC_AWAY 1044
+#define IDC_KLEVERNET 1045
+#define IDC_NOTHERE 1046
+#define IDC_REFUSE 1047
+#define IDC_DOWINLIMIT 1051
+#define IDC_TIMESPIN 1052
+#define IDC_WINSPIN 1053
+#define IDC_NTALKPORT 1053
+#define IDC_CHARSPIN 1054
+#define IDC_NTALKPORTSPIN 1054
+#define ID_TALK_ABORT 32771
+#define ID_TALK_CLOSE 32772
+#define ID_WINDOW_CENTERSPLITTER 32773
+#define ID_WINDOW_SPLITEQUALLY 32774
+#define ID_WINDOW_SAVELAYOUT 32775
+#define ID_WINDOW_AUTOSAVELAYOUT 32776
+#define ID_TALK_REMOTEUSER 32777
+#define ID_WINDOW_HORIZONTALSPLIT 32778
+#define ID_WINDOW_VERTICALSPLIT 32779
+#define ID_TRAY_T42 32780
+#define ID_TRAY_OPTIONS 32781
+#define ID_TRAY_SHOWMAINWINDOW 32782
+#define ID_TRAY_EXIT 32783
+#define ID_TALK_RECONNECT 32784
+#define ID_WINDOW_HIDEINTRAYONMINIMIZE 32785
+#define ID_SLEEP_SLEEP 32786
+#define ID_SLEEP_MAKESOUND 32788
+#define ID_SLEEP_POPUP 32789
+#define ID_SLEEP_WAKEUPACTION_MAKESOUND 32790
+#define ID_SLEEP_WAKEUPACTION_POPUP 32791
+#define ID_SLEEP_SLEEPONMINIMIZE 32792
+#define ID_SLEEP_MINIMIZEONSLEEP 32793
+#define ID_CALLLOG_CALLBACK 32794
+#define ID_CALLLOG_DELETE 32795
+#define ID_CALLLOG_SAVETOFILE 32796
+#define ID_CALLLOG_EMPTYLOG 32797
+#define ID_CALLLOG_MARKASNEW 32798
+#define ID_CALLLOG_MARKASPROCESSED 32799
+#define ID_TRAY_AWAY 32800
+#define ID_TEA_SAVE 32801
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 151
+#define _APS_NEXT_COMMAND_VALUE 32802
+#define _APS_NEXT_CONTROL_VALUE 1055
+#define _APS_NEXT_SYMED_VALUE 106
+#endif
+#endif
diff --git a/shared-code/BTreendex.h b/shared-code/BTreendex.h
new file mode 100644
index 0000000..88109ab
--- a/dev/null
+++ b/shared-code/BTreendex.h
@@ -0,0 +1,595 @@
+#ifndef __BTREENDEX_H
+#define __BTREENDEX_H
+
+#include "Dynamide.h"
+
+namespace Klever {
+
+template<class key,class value,int treeOrder,int cluster>
+class CBTreendex : public CObject {
+public:
+ typedef LONG CBTPageRef;
+ struct CBTRecordRef {
+ CBTPageRef m_Page;
+ INT m_Offset;
+ CBTRecordRef(CBTPageRef page=-1,INT offset=-1) : m_Page(page), m_Offset(offset) {}
+ };
+ class CBTRecord : public CObject {
+ public:
+ CBTPageRef m_ptrLeft;
+ CBTPageRef m_ptrRight;
+ key m_Key;
+ value m_Value;
+ CBTRecord() : m_ptrLeft(-1), m_ptrRight(-1) {}
+ CBTRecord(key& _key,value& _value,CBTPageRef left=-1,CBTPageRef right=-1) : m_Key(_key), m_Value(_value), m_ptrLeft(left), m_ptrRight(right) {}
+ CBTRecord(CBTRecord& r) : m_Key(r.m_Key), m_Value(r.m_Value), m_ptrLeft(r.m_ptrLeft), m_ptrRight(r.m_ptrRight) {}
+
+ CBTRecord& operator=(CBTRecord& r) {m_Key=r.m_Key, m_Value=r.m_Value, m_ptrLeft=r.m_ptrLeft, m_ptrRight=r.m_ptrRight;return *this;}
+
+ void Serialize(CArchive& ar) {
+ if(ar.IsStoring()){
+ ar << m_ptrLeft;
+ ar << m_ptrRight;
+ }else{
+ ar >> m_ptrLeft;
+ ar >> m_ptrRight;
+ }
+ SerializeElements(ar,&m_Key,1);
+ SerializeElements(ar,&m_Value,1);
+ }
+ };
+ class CBTPage : public CArray<CBTRecord,CBTRecord&> {
+ public:
+ void Serialize(CArchive& ar) {
+ int nCount = -1;
+ if(ar.IsStoring()){
+ nCount = GetSize();
+ ar << nCount;
+ }else{
+ nCount = 0;
+ ar >> nCount;
+ RemoveAll();
+ SetSize(nCount);
+ }
+ for(int tmp=0;tmp<nCount;tmp++)
+ ElementAt(tmp).Serialize(ar);
+ }
+ };
+ typedef CDynamide<256,cluster> CBTDyna;
+ typedef CBTDyna::CDynaFile CBTDynaFile;
+ typedef CArray<CBTRecordRef,CBTRecordRef&> CBTRStack;
+
+ CBTDyna m_BT;
+ struct _btCrap {
+ BOOL m_bRootSet;
+ CBTPageRef m_Root;
+ } *m_BTCrap;
+ BOOL m_bRO;
+ CBTRStack m_btStack;
+ CBTPage m_stackTop;
+
+ CBTreendex() {}
+ ~CBTreendex() { Close(); }
+ BOOL Attach(CFile* file,BOOL bAutodelete) {
+ m_bRO = FALSE;
+ if(!m_BT.Attach(file,bAutodelete))
+ return FALSE;
+ return Attach();
+ }
+ BOOL Open(LPCTSTR file,BOOL bReadOnly) {
+ if(!m_BT.Open(file,bReadOnly))
+ return FALSE;
+ m_bRO = bReadOnly;
+ return Attach();
+ }
+ BOOL Create(LPCTSTR file) {
+ try{
+ CFile* f = new CFile(file,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyRead|CFile::shareDenyWrite|CFile::typeBinary);
+ ASSERT(f);
+ return Attach(f,TRUE);
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ }
+ BOOL Attach() {
+ ASSERT(m_BT.IsOpened());
+ m_BTCrap = (_btCrap*)m_BT.m_FB.crap;
+ if(!m_BTCrap->m_bRootSet){
+ m_BTCrap->m_Root = AllocatePage();
+ if(m_BTCrap->m_Root<0)
+ return FALSE;
+ m_BTCrap->m_bRootSet = TRUE;
+ m_BT.Write1stBlock();
+ }
+ return TRUE;
+ }
+ BOOL Close() {
+ m_BT.Close();
+ return TRUE;
+ }
+ BOOL IsOpened() {
+ return m_BT.IsOpened();
+ }
+
+ BOOL Lookup(key& _key,value& value) {
+ if(!IsOpened())
+ return FALSE;
+ ASSERT(m_BTCrap->m_bRootSet);
+ if(!SeekToPage(_key))
+ return FALSE;
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(rr.m_Offset<0)
+ return FALSE;
+ ASSERT(rr.m_Offset<m_stackTop.GetSize());
+ if(_key != m_stackTop[rr.m_Offset].m_Key)
+ return FALSE;
+ value = m_stackTop[rr.m_Offset].m_Value;
+ return TRUE;
+ }
+ BOOL Add(key& _key,value& _value) {
+ if(!IsOpened())
+ return FALSE;
+ ASSERT(m_BTCrap->m_bRootSet);
+ if(!SeekToPage(_key))
+ return FALSE;
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ CBTRecord nuRecord(_key,_value);
+ if(rr.m_Offset<0){
+ if(m_stackTop.GetSize())
+ nuRecord.m_ptrLeft = m_stackTop[m_stackTop.GetUpperBound()].m_ptrRight;
+ }else if(rr.m_Offset==0){
+ nuRecord.m_ptrRight = m_stackTop[0].m_ptrLeft;
+ }else{
+ nuRecord.m_ptrLeft = m_stackTop[rr.m_Offset-1].m_ptrRight;
+ nuRecord.m_ptrRight = m_stackTop[rr.m_Offset].m_ptrLeft;
+ }
+// ASSERT(rr.m_Offset==0 || (m_stackTop[rr.m_Offset-1].m_Key<_key && m_stackTop[rr.m_Offset-1].m_ptrRight<0));
+// ASSERT(rr.m_Offset<0 || m_stackTop[rr.m_Offset].m_Key>=_key && m_stackTop[rr.m_Offset].m_ptrLeft<0);
+ if(rr.m_Offset>=0 && m_stackTop[rr.m_Offset].m_Key==_key){
+ // Exact match found - just replace.
+ m_stackTop[rr.m_Offset].m_Value = _value;
+ if(!SavePage(rr.m_Page,m_stackTop))
+ return FALSE;
+ return TRUE;
+ }
+ // Split the page and propagate the split if needed..
+ // Insert new element at rr.m_Offset..
+ BOOL nuisnew = TRUE;
+ for(int sp=m_btStack.GetUpperBound();sp>=0;sp--){
+ CBTPageRef opr = m_btStack[sp].m_Page;
+ int iAt = m_btStack[sp].m_Offset;
+ CBTPage op;
+ VERIFY(LoadPage(opr,op));
+ if(iAt<0)
+ iAt = op.GetSize();
+ else{
+ if(op[iAt].m_Key<nuRecord.m_Key)
+ iAt++;
+ ASSERT(iAt==op.GetSize() || op[iAt].m_Key > nuRecord.m_Key);
+ }
+ op.InsertAt(iAt,nuRecord);
+ if(iAt>0)
+ op[iAt-1].m_ptrRight=nuRecord.m_ptrLeft;
+ if(iAt<op.GetUpperBound())
+ op[iAt+1].m_ptrLeft=nuRecord.m_ptrRight;
+ if(op.GetSize()<=treeOrder*2){
+ // This isn't causing overflow
+ VERIFY(SavePage(opr,op));
+ return TRUE;
+ }
+ TRACE0("Split\n");
+ ASSERT(op.GetSize()==(treeOrder*2+1));
+ CBTPageRef npr = AllocatePage();
+ ASSERT(npr>=0);
+ CBTPage np;
+ ASSERT(LoadPage(npr,np));
+ ASSERT(!np.GetSize());
+ nuRecord = op[treeOrder];
+ if(iAt==treeOrder){
+ // We're inserting central element! - drop out the stack top if this is still new one
+ for(int tmp=0;tmp<treeOrder;tmp++)
+ np.InsertAt(tmp,op[tmp]);
+ op.RemoveAt(0,treeOrder+1);
+ nuRecord.m_ptrLeft = npr;
+ nuRecord.m_ptrRight = opr;
+ if(nuisnew)
+ m_btStack.RemoveAt(m_btStack.GetUpperBound());
+ }else{
+ if(iAt<treeOrder){
+ // We're inserting in the left subtree.
+ // Make newpage the right one and forget it.
+ for(int tmp=0;tmp<treeOrder;tmp++)
+ np.InsertAt(tmp,op[tmp+treeOrder+1]);
+ op.RemoveAt(treeOrder,treeOrder+1);
+ nuRecord.m_ptrLeft = opr;
+ nuRecord.m_ptrRight = npr;
+ }else{
+ // We're inserting in the right subtree.
+ // Make newpage the left one, forget it, but also adjust offset in the stack
+ for(int tmp=0;tmp<treeOrder;tmp++)
+ np.InsertAt(tmp,op[tmp]);
+ op.RemoveAt(0,treeOrder+1);
+ nuRecord.m_ptrLeft = npr;
+ nuRecord.m_ptrRight = opr;
+ m_btStack[sp].m_Offset-=treeOrder+1;
+ }
+ // Note that we're not inserting new element anymore.
+ nuisnew = FALSE;
+ }
+ // Do, excessive sanity checks and save pages
+ ASSERT(op.GetSize());
+ ASSERT(np.GetSize());
+ VERIFY(SavePage(opr,op));
+ VERIFY(SavePage(npr,np));
+ }
+ // Here we have root page overflow, which means that we're simply putting new
+ // record in this brand new root page and also inserting this page on the bottom of the stack
+ CBTPageRef nuroot = AllocatePage();
+ ASSERT(nuroot>=0);
+ CBTPage nurpa;
+ ASSERT(LoadPage(nuroot,nurpa));
+ ASSERT(!nurpa.GetSize());
+ nurpa.Add(nuRecord);
+ VERIFY(SavePage(nuroot,nurpa));
+ m_btStack.InsertAt(0,CBTRecordRef(nuroot,0));
+ m_BTCrap->m_Root = nuroot;
+ m_BT.Write1stBlock();
+ return TRUE;
+ }
+ BOOL Delete(key& _key) {
+ if(!IsOpened())
+ return FALSE;
+ ASSERT(m_BTCrap->m_bRootSet);
+ value _value;
+ if(!Lookup(_key,_value))
+ return FALSE;
+ // Found key, check if it's a leaf
+ {
+ CBTRecordRef* rr = &m_btStack[m_btStack.GetUpperBound()];
+ int rrIdx = m_btStack.GetUpperBound();
+ if(m_stackTop[rr->m_Offset].m_ptrLeft>=0){
+ ASSERT(m_stackTop[rr->m_Offset].m_ptrRight>=0);
+ // It isn't - scan for the _next_ key and do dirty deeds
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr->m_Offset].m_ptrRight,0));
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ if(m_stackTop[0].m_ptrLeft<0)
+ break;
+ m_btStack.Add(CBTRecordRef(m_stackTop[0].m_ptrLeft,0));
+ }
+ // We have a leaf node here, replace victim with the first element and kill it.
+ CBTPage uppage;
+ rr = &m_btStack[rrIdx];
+ if(!LoadPage(rr->m_Page,uppage))
+ return FALSE;
+ uppage[rr->m_Offset].m_Key=m_stackTop[0].m_Key; uppage[rr->m_Offset].m_Value=m_stackTop[0].m_Value;
+ m_stackTop.RemoveAt(0);
+ if(!(SavePage(rr->m_Page,uppage) && SavePage(m_btStack[m_btStack.GetUpperBound()].m_Page,m_stackTop)))
+ return FALSE;
+ }else{
+ ASSERT(m_stackTop[rr->m_Offset].m_ptrRight<0);
+ m_stackTop.RemoveAt(rr->m_Offset);
+ if(!SavePage(rr->m_Page,m_stackTop))
+ return FALSE;
+ }
+ }
+ // We have a page to check for underflow at the top of the stack now.
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ if(m_stackTop.GetSize()>=treeOrder || m_btStack.GetSize()==1)
+ return TRUE;
+ CBTRecordRef& rr1 = m_btStack[m_btStack.GetUpperBound()-1];
+ CBTPage daddy;
+ if(!LoadPage(rr1.m_Page,daddy))
+ return FALSE;
+ CBTPageRef nPage = daddy[rr1.m_Offset].m_ptrRight;
+ BOOL bRight=TRUE;
+ if(nPage<0 || nPage==rr.m_Page){
+ nPage = daddy[rr1.m_Offset].m_ptrLeft;
+ bRight = FALSE;
+ }
+ ASSERT(nPage>=0 && nPage!=rr.m_Page);
+ CBTPage neighbor;
+ if(!LoadPage(nPage,neighbor))
+ return FALSE;
+ // Here we have possibly two cases:
+ // 1. Neighboring page can share some data with use, then do share and leave
+ // 2. Neighboring page is of treeorder in size, then merge and propagate
+ if(neighbor.GetSize()>treeOrder){
+ TRACE0("Redistributing..\n");
+ // Borrow some data from there.
+ int toBorrow = neighbor.GetSize()-treeOrder;
+ toBorrow=toBorrow/2+1;
+ ASSERT(toBorrow);
+ if(bRight)
+ m_stackTop.Add(CBTRecord(daddy[rr1.m_Offset].m_Key,daddy[rr1.m_Offset].m_Value,m_stackTop[m_stackTop.GetUpperBound()].m_ptrRight,neighbor[0].m_ptrLeft));
+ else
+ m_stackTop.InsertAt(0,CBTRecord(daddy[rr1.m_Offset].m_Key,daddy[rr1.m_Offset].m_Value,neighbor[neighbor.GetUpperBound()].m_ptrRight,m_stackTop[0].m_ptrLeft));
+ for(toBorrow--;toBorrow;toBorrow--){
+ if(bRight){
+ m_stackTop.Add(neighbor[0]);
+ neighbor.RemoveAt(0);
+ }else{
+ m_stackTop.InsertAt(0,neighbor[neighbor.GetUpperBound()]);
+ neighbor.RemoveAt(neighbor.GetUpperBound());
+ }
+ }
+ daddy[rr1.m_Offset].m_Key = neighbor[bRight?0:neighbor.GetUpperBound()].m_Key; daddy[rr1.m_Offset].m_Value = neighbor[bRight?0:neighbor.GetUpperBound()].m_Value;
+ neighbor.RemoveAt(bRight?0:neighbor.GetUpperBound());
+ if(!(SavePage(rr1.m_Page,daddy) && SavePage(nPage,neighbor) && SavePage(rr.m_Page,m_stackTop)))
+ return FALSE;
+ rr.m_Offset = -1; // *** Point to the next??
+ return TRUE;
+ }
+ TRACE0("Merging..\n");
+ // We need to merge pages here..
+ // We will merge them at stacktop, then we'll discard neighbor guy..
+ if(bRight)
+ m_stackTop.Add(CBTRecord(daddy[rr1.m_Offset].m_Key,daddy[rr1.m_Offset].m_Value,m_stackTop[m_stackTop.GetUpperBound()].m_ptrRight,neighbor[0].m_ptrLeft));
+ else
+ m_stackTop.InsertAt(0,CBTRecord(daddy[rr1.m_Offset].m_Key,daddy[rr1.m_Offset].m_Value,neighbor[neighbor.GetUpperBound()].m_ptrRight,m_stackTop[0].m_ptrLeft));
+ if(bRight){
+ while(neighbor.GetSize()){
+ m_stackTop.Add(neighbor[0]);
+ neighbor.RemoveAt(0);
+ }
+ }else{
+ while(neighbor.GetSize()){
+ m_stackTop.InsertAt(0,neighbor[neighbor.GetUpperBound()]);
+ neighbor.RemoveAt(neighbor.GetUpperBound());
+ }
+ }
+ if(rr1.m_Offset>0)
+ daddy[rr1.m_Offset-1].m_ptrRight=rr.m_Page;
+ if(rr1.m_Offset<daddy.GetUpperBound())
+ daddy[rr1.m_Offset+1].m_ptrLeft=rr.m_Page;
+ daddy.RemoveAt(rr1.m_Offset);
+ if(!(SavePage(rr1.m_Page,daddy) && SavePage(rr.m_Page,m_stackTop)))
+ return FALSE;
+ VERIFY(DeallocatePage(nPage));
+ m_btStack.RemoveAt(m_btStack.GetUpperBound());
+ }
+ return FALSE;
+ }
+ BOOL GoFirst() {
+ if(!IsOpened())
+ return FALSE;
+ ASSERT(m_BTCrap->m_bRootSet);
+ m_btStack.RemoveAll();
+ m_btStack.Add(CBTRecordRef(m_BTCrap->m_Root,-1));
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ if(!m_stackTop.GetSize()){
+ ASSERT(m_btStack.GetSize()==1);
+ return FALSE;
+ }
+ rr.m_Offset = 0;
+ if(m_stackTop[rr.m_Offset].m_ptrLeft<0)
+ return TRUE;
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,-1));
+ }
+ }
+ BOOL GoLast() {
+ if(!IsOpened())
+ return FALSE;
+ ASSERT(m_BTCrap->m_bRootSet);
+ m_btStack.RemoveAll();
+ m_btStack.Add(CBTRecordRef(m_BTCrap->m_Root,-1));
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ if(!m_stackTop.GetSize()){
+ ASSERT(m_btStack.GetSize()==1);
+ return FALSE;
+ }
+ rr.m_Offset = m_stackTop.GetUpperBound();
+ if(m_stackTop[rr.m_Offset].m_ptrRight<0)
+ return TRUE;
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset++].m_ptrRight,-1));
+ }
+ }
+ BOOL GoNext() {
+ if(!IsOpened())
+ return FALSE;
+ if(!(m_btStack.GetSize() && m_btStack[m_btStack.GetUpperBound()].m_Offset>=0))
+ return FALSE;
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ ASSERT(rr.m_Offset<m_stackTop.GetSize());
+ if(m_stackTop[rr.m_Offset].m_ptrRight>=0){
+ // Advance pointer in this page and dive into subtree
+ // going left and left until we have nowhere to go.
+// TRACE1("Dive into page %lu",m_stackTop[rr.m_Offset].m_ptrRight);
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset++].m_ptrRight,0));
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ ASSERT(rr.m_Offset==0);
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ if(m_stackTop[rr.m_Offset].m_ptrLeft<0)
+ break;
+// TRACE1(", %lu",m_stackTop[rr.m_Offset].m_ptrLeft);
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,0));
+ }
+// TRACE0("\n");
+ return TRUE;
+ }else if(rr.m_Offset<m_stackTop.GetUpperBound()){
+ rr.m_Offset++;
+ return TRUE;
+ }
+ // We're at the end of page go up until we're done or we have data.
+ m_btStack.RemoveAt(m_btStack.GetUpperBound());
+// TRACE0("Go up");
+ while(m_btStack.GetSize()){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ if(rr.m_Offset<m_stackTop.GetSize()){
+// TRACE0("\n");
+ return TRUE;
+ }
+// TRACE0(", up");
+ m_btStack.RemoveAt(m_btStack.GetUpperBound());
+ }
+// TRACE0("\nBtree is done\n");
+ return FALSE;
+ }
+ BOOL GoPrev() {
+ if(!IsOpened())
+ return FALSE;
+ if(!(m_btStack.GetSize() && m_btStack[m_btStack.GetUpperBound()].m_Offset>=0))
+ return FALSE;
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ ASSERT(rr.m_Offset<m_stackTop.GetSize());
+ if(m_stackTop[rr.m_Offset].m_ptrLeft>=0){
+ // Dive in and go right and right from the rightmost until
+ // we have nowhere to go.
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,-1));
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ rr.m_Offset = m_stackTop.GetUpperBound();
+ if(m_stackTop[rr.m_Offset].m_ptrRight<0)
+ return TRUE;
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset++].m_ptrRight,-1));
+ }
+ return TRUE;
+ }else if(rr.m_Offset>0){
+ rr.m_Offset--;
+ return TRUE;
+ }
+ // We're at the leftmost element in page - go up and left until we're
+ // done or we have data.
+ m_btStack.RemoveAt(m_btStack.GetUpperBound());
+ while(m_btStack.GetSize()){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ rr.m_Offset--;
+ if(rr.m_Offset>=0)
+ return TRUE;
+ m_btStack.RemoveAt(m_btStack.GetUpperBound());
+ }
+ // No more data - we were at the first element in tree.
+ return FALSE;
+ }
+ BOOL GetThis(key& _key,value& _value) {
+ if(!IsOpened())
+ return FALSE;
+ // *** MORE CHECKING
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ _key = m_stackTop[rr.m_Offset].m_Key;
+ _value = m_stackTop[rr.m_Offset].m_Value;
+ return TRUE;
+ }
+
+ BOOL SeekToPage(const key& _key) {
+ ASSERT(IsOpened());
+ ASSERT(m_BTCrap->m_bRootSet);
+ m_btStack.RemoveAll();
+ m_btStack.Add(CBTRecordRef(m_BTCrap->m_Root,-1));
+ for(;;){
+ CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
+ if(!LoadPage(rr.m_Page,m_stackTop))
+ return FALSE;
+ ASSERT(m_stackTop.GetSize() || !m_btStack.GetUpperBound());
+ if(!m_stackTop.GetSize()){
+ rr.m_Offset=-1;
+ return TRUE;
+ }
+ for(rr.m_Offset=0;rr.m_Offset<m_stackTop.GetSize();rr.m_Offset++){
+ if(_key == m_stackTop[rr.m_Offset].m_Key)
+ return TRUE;
+ if(_key < m_stackTop[rr.m_Offset].m_Key){
+ ASSERT(rr.m_Offset==0 || m_stackTop[rr.m_Offset].m_ptrLeft==m_stackTop[rr.m_Offset-1].m_ptrRight);
+ if(m_stackTop[rr.m_Offset].m_ptrLeft<0)
+ return TRUE;
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,-1));
+ break;
+ }
+ if(rr.m_Offset==m_stackTop.GetUpperBound()){
+ if(m_stackTop[rr.m_Offset].m_ptrRight<0){
+ rr.m_Offset=-1;
+ return TRUE;
+ }
+ m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrRight,-1));
+ break;
+ }
+ }
+ }
+ }
+
+ BOOL LoadPage(CBTPageRef ref,CBTPage& page) {
+ CFile* pageFile = m_BT.OpenFile(ref);
+ if(!pageFile)
+ return FALSE;
+ BOOL rv = TRUE;
+ try{
+ CArchive ar(pageFile,CArchive::load);
+ page.Serialize(ar);
+ if(m_bRO)
+ page.FreeExtra(); // ** ???
+ ar.Close();
+ }catch(CException* e){
+ e->Delete();
+ rv = FALSE;
+ }
+ delete pageFile;
+ return rv;
+ }
+ BOOL SavePage(CBTPageRef ref,CBTPage& page) {
+ CFile* pageFile = m_BT.OpenFile(ref);
+ if(!pageFile)
+ return FALSE;
+ BOOL rv = TRUE;
+ try{
+ CArchive ar(pageFile,CArchive::store);
+ page.Serialize(ar);
+ ar.Close();
+ }catch(CException* e){
+ e->Delete();
+ rv = FALSE;
+ }
+ delete pageFile;
+ return rv;
+ }
+ CBTPageRef AllocatePage() {
+ CBTDynaFile* pageFile = m_BT.CreateFile();
+ if(!pageFile)
+ return -1;
+ CBTPage nothing;
+ CBTPageRef rv = pageFile->GetFile();
+ try{
+ CArchive ar(pageFile,CArchive::store);
+ nothing.Serialize(ar);
+ ar.Close();
+ }catch(CException* e){
+ e->Delete();
+ rv = -1;
+ }
+ delete pageFile;
+ return rv;
+ }
+ BOOL DeallocatePage(CBTPageRef ref) {
+ return m_BT.DeleteFile(ref);
+ }
+
+};
+
+};
+
+#endif // __BTREENDEX_H
diff --git a/shared-code/BellsNWhistles.h b/shared-code/BellsNWhistles.h
new file mode 100644
index 0000000..1de77ae
--- a/dev/null
+++ b/shared-code/BellsNWhistles.h
@@ -0,0 +1,146 @@
+#ifndef __BELLSNWHISTLES_H
+#define __BELLSNWHISTLES_H
+
+class CBellsNWhistles {
+public:
+ class CBang {
+ public:
+ CString m_codeName;
+ enum _bangType {
+ bangNone, bangSpeaker, bangSystem, bangResource,
+ bangWaveform
+ } m_type;
+ BOOL m_bLoop;
+ union {
+ UINT system;
+ LPCTSTR resource;
+ LPCTSTR wave;
+
+ LPCTSTR str;
+ UINT id;
+ };
+ CString m_strWave;
+ CBang() : m_type(bangNone), m_bLoop(FALSE) {}
+ };
+ typedef CTypedPtrMap<CMapStringToPtr,CString,CBang*> CBangs;
+ struct CBelling {
+ LPCSTR snd;
+ HMODULE hm;
+ DWORD flags;
+ CBelling(LPCSTR snd,HMODULE hm,DWORD flags) : snd(snd), hm(hm),
+ flags(flags) {}
+ CBelling(CBelling& s) : snd(s.snd), hm(s.hm), flags(s.flags) {}
+ CBelling& operator=(CBelling& s) {
+ snd=s.snd; hm=s.hm; flags=s.flags;
+ return *this;
+ }
+ };
+ typedef CBelling* Whistling;
+
+ CBangs m_bangs;
+
+ ~CBellsNWhistles() {
+ POSITION p = m_bangs.GetStartPosition();
+ while(p){
+ CString s; CBang* b;
+ m_bangs.GetNextAssoc(p,s,b);
+ delete b;
+ }
+ m_bangs.RemoveAll();
+ }
+
+ BOOL AssignSound(LPCTSTR codeName,LPCTSTR id,CBang::_bangType type=CBang::bangWaveform) {
+ CString cn = codeName;
+ cn.MakeLower();
+ CBang* b;
+ if(!m_bangs.Lookup(cn,b)) {
+ b = new CBang;
+ b->m_codeName=cn;
+ m_bangs[cn]=b;
+ }
+ b->m_type=type;
+ b->str = id;
+ if(type==CBang::bangWaveform){
+ b->m_strWave=id; b->str = b->m_strWave;
+ }
+ return TRUE;
+ }
+ BOOL AssignSound(LPCTSTR codeName,UINT nID,CBang::_bangType type=CBang::bangResource) {
+ CString cn = codeName;
+ cn.MakeLower();
+ CBang* b;
+ if(!m_bangs.Lookup(cn,b)) {
+ b = new CBang;
+ b->m_codeName=cn;
+ m_bangs[cn]=b;
+ }
+ b->m_type=type;
+ b->id = nID;
+ ASSERT(type!=CBang::bangWaveform);
+ return TRUE;
+ }
+ BOOL UnassignSound(LPCTSTR codeName) {
+ CString cn = codeName;
+ cn.MakeLower();
+ CBang* b;
+ if(m_bangs.Lookup(cn,b)) {
+ m_bangs.RemoveKey(cn);
+ delete b;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ Whistling StartSound(LPCTSTR codeName) {
+ Whistling* rv = NULL;
+ CString cn = codeName;
+ CBang* b;
+ if(!m_bangs.Lookup(cn,b)){
+ ::PlaySound(cn,AfxGetInstanceHandle(),SND_ASYNC|SND_NODEFAULT|SND_NOWAIT|SND_FILENAME);
+ return NULL;
+ }
+ UINT flags = SND_ASYNC|SND_NODEFAULT|SND_NOWAIT;
+ LPCSTR snd = NULL;
+ switch(b->m_type){
+ case CBang::bangNone: return NULL;
+ case CBang::bangSpeaker: MessageBeep(0xFFFFFFFF); return NULL;
+ case CBang::bangSystem: MessageBeep(b->system); return NULL;
+ case CBang::bangResource:
+ snd = b->resource;
+ flags|=SND_RESOURCE; break;
+ case CBang::bangWaveform:
+ snd = b->wave;
+ flags|=SND_FILENAME; break;
+#ifdef _DEBUG
+ default:
+ ASSERT(FALSE); return NULL;
+#endif
+ }
+ if(b->m_bLoop)
+ flags|=SND_LOOP;
+ HMODULE hm = AfxGetInstanceHandle();
+ if(!::PlaySound(snd,hm,flags))
+ return NULL;
+ return b->m_bLoop?new CBelling(snd,hm,flags):NULL;
+ }
+ BOOL StopSound(Whistling whistle) {
+ if(!whistle)
+ return FALSE;
+ ::PlaySound(whistle->snd,whistle->hm,whistle->flags|SND_PURGE);
+ delete whistle;
+ return TRUE;
+ }
+ UINT FillInCombo(CComboBox* combo) {
+ POSITION p = m_bangs.GetStartPosition();
+ UINT rv = 0;
+ while(p) {
+ CString s;
+ CBang* b;
+ m_bangs.GetNextAssoc(p,s,b);
+ combo->AddString(s);
+ }
+ return rv;
+ }
+};
+
+#endif // _BELLSNWHISTLES_H \ No newline at end of file
diff --git a/shared-code/BitSet.h b/shared-code/BitSet.h
new file mode 100644
index 0000000..cf36e3b
--- a/dev/null
+++ b/shared-code/BitSet.h
@@ -0,0 +1,105 @@
+#ifndef __BITSET_H
+#define __BITSET_H
+
+namespace Klever {
+
+class CBitSet : public CObject {
+public:
+ CWordArray m_Bits;
+ ULONG m_BitsInSet;
+ enum {
+ bitsPerWord = sizeof(WORD)*8
+ };
+
+ CBitSet(ULONG size = 0) : m_BitsInSet(0) { SetSize(size); }
+ CBitSet(CBitSet& o) : m_BitsInSet(0) { CopyFrom(o); }
+
+ void SetSize(ULONG size,BOOL bFillOnes=FALSE) {
+ UINT os = m_Bits.GetSize();
+ UINT ns = (size+bitsPerWord-1)/bitsPerWord;
+ if(os==ns){
+ if(os){
+ if(bFillOnes)
+ m_Bits[m_BitsInSet/bitsPerWord]|=(~(WORD)0)<<(m_BitsInSet%bitsPerWord);
+ else
+ m_Bits[m_BitsInSet/bitsPerWord]&=~((~(WORD)0)<<(m_BitsInSet%bitsPerWord));
+ }
+ m_BitsInSet=size;
+ }else{
+ // *?* ASSERT((!os) || (((os-1)*bitsPerWord)<=m_BitsInSet && m_BitsInSet<(os*bitsPerWord)));
+ if(os<ns){
+ m_Bits.SetSize(ns);
+ if(bFillOnes)
+ m_Bits[m_BitsInSet/bitsPerWord]|=(~(WORD)0)<<(m_BitsInSet%bitsPerWord);
+ else
+ m_Bits[m_BitsInSet/bitsPerWord]&=~((~(WORD)0)<<(m_BitsInSet%bitsPerWord));
+ WORD* ws = m_Bits.GetData();
+ ASSERT(ws);
+ memset(&ws[os],bFillOnes?0xFF:0,(ns-os)*sizeof(WORD));
+ m_BitsInSet=size;
+ }else{
+ m_Bits.SetSize(ns);
+ m_BitsInSet=size;
+ }
+ }
+ }
+ BOOL BitSet(UINT bit,BOOL bGrow=TRUE) { return SetBit(bit,TRUE,bGrow); }
+ BOOL BitClear(UINT bit,BOOL bGrow=TRUE) { return SetBit(bit,FALSE,bGrow); }
+ BOOL SetBit(UINT bit,BOOL state,BOOL bGrow=TRUE) {
+ if(m_BitsInSet<=bit){
+ if(!bGrow)
+ return FALSE;
+ SetSize(bit+1);
+ }
+ WORD mask = ((WORD)1)<<(bit%bitsPerWord);
+ if(state)
+ m_Bits[bit/bitsPerWord]|=mask;
+ else
+ m_Bits[bit/bitsPerWord]&=~mask;
+ return TRUE;
+ }
+ BOOL IsSet(UINT bit) {
+ if(m_BitsInSet<=bit)
+ return FALSE;
+ return (m_Bits[bit/bitsPerWord]&(((WORD)1)<<(bit%bitsPerWord)))!=0;
+ }
+ void Invert() {
+ for(int i=m_Bits.GetUpperBound();i>=0;i--)
+ m_Bits[i]=~m_Bits[i];
+ }
+ CBitSet& operator&=(CBitSet& o) {
+ if(o.m_BitsInSet<m_BitsInSet)
+ SetSize(o.m_BitsInSet);
+ for(int i=m_Bits.GetUpperBound();i>=0;i--)
+ m_Bits[i]&=o.m_Bits[i];
+ return *this;
+ }
+ CBitSet& operator|=(CBitSet& o) {
+ if(o.m_BitsInSet>m_BitsInSet)
+ SetSize(o.m_BitsInSet);
+ for(int i=o.m_Bits.GetUpperBound();i>=0;i--)
+ m_Bits[i]|=o.m_Bits[i];
+ return *this;
+ }
+ CBitSet& operator=(CBitSet& o) {
+ CopyFrom(o);
+ return *this;
+ }
+ void CopyFrom(CBitSet& o) {
+ m_BitsInSet=o.m_BitsInSet;
+ m_Bits.Copy(o.m_Bits);
+ }
+ void Serialize(CArchive& ar) {
+ if(ar.IsStoring()){
+ ar << m_BitsInSet;
+ m_Bits.Serialize(ar);
+ }else{
+ ar >> m_BitsInSet;
+ m_Bits.Serialize(ar);
+ }
+ }
+};
+
+};
+
+#endif // __BITSET_H
diff --git a/shared-code/Dynamide.h b/shared-code/Dynamide.h
new file mode 100644
index 0000000..32c93f7
--- a/dev/null
+++ b/shared-code/Dynamide.h
@@ -0,0 +1,443 @@
+#ifndef __DYNAMIDE_H
+#define __DYNAMIDE_H
+
+#include "LRUCache.h"
+
+namespace Klever {
+
+template<int fbSize,int bSize>
+class CDynamide : public CObject {
+ struct firstBlock {
+ LONG freeFile;
+ BYTE crap[fbSize-sizeof(LONG)];
+ };
+ struct theBlock {
+ LONG next;
+ BYTE data[bSize-sizeof(LONG)];
+ };
+public:
+ static firstBlock FirstBlock;
+ static theBlock TheBlock;
+private:
+ class CDynaCache : public CLRUCache<DWORD,DWORD,theBlock> {
+ public:
+ CFile* m_File;
+ BOOL m_bAutodelete;
+ CDynaCache(CFile* file,BOOL bAutodelete=TRUE) : CLRUCache<DWORD,DWORD,theBlock>(64) {
+ m_File=file;
+ m_bAutodelete=bAutodelete;
+ }
+ virtual ~CDynaCache() {
+ Flush();
+ if(m_bAutodelete){
+ m_File->Close();
+ delete m_File;
+ }
+ }
+ virtual BOOL _ReadIn(DWORD idx,theBlock* data) {
+ LONG p = sizeof(firstBlock)+idx*sizeof(theBlock);
+ LONG s = m_File->Seek(p,CFile::begin);
+ if(p==s){
+ UINT rb = m_File->Read(data,sizeof(*data));
+ if(rb==sizeof(*data))
+ return TRUE;
+ if(rb)
+ return FALSE;
+ memset(data,0,sizeof(*data));
+ data->next=-1;
+ try{
+ m_File->Write(data,sizeof(*data));
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ }else{
+ LONG togo = p-s;
+ ASSERT(togo>0);
+ ASSERT(!(togo%sizeof(theBlock)));
+ memset(data,0,sizeof(*data));
+ data->next=-1;
+ while(togo>=0){
+ try{
+ m_File->Write(data,sizeof(*data));
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+ }
+ virtual BOOL _WriteOut(DWORD idx,theBlock* data) {
+ LONG p = sizeof(firstBlock)+idx*sizeof(theBlock);
+ LONG s = m_File->Seek(p,CFile::begin);
+ if(p!=s)
+ return FALSE;
+ try{
+ m_File->Write(data,sizeof(*data));
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ return TRUE;
+ }
+ DWORD AllocateNode() {
+ LONG l = m_File->GetLength();
+ ASSERT(!((l-sizeof(firstBlock))%sizeof(theBlock)));
+ m_File->SetLength(l+sizeof(theBlock));
+ return (l-sizeof(firstBlock))/sizeof(theBlock);
+ }
+ BOOL Read1stBlock(firstBlock* fb) {
+ m_File->SeekToBegin();
+ UINT rb = m_File->Read(fb,sizeof(*fb));
+ if(rb==sizeof(*fb))
+ return TRUE;
+ if(rb)
+ return FALSE;
+ memset(fb,0,sizeof(*fb));
+ fb->freeFile = -1;
+ try{
+ m_File->Write(fb,sizeof(*fb));
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ return TRUE;
+ }
+ BOOL Write1stBlock(firstBlock* fb) {
+ m_File->SeekToBegin();
+ try{
+ m_File->Write(fb,sizeof(*fb));
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ return TRUE;
+ }
+ };
+public:
+ class CDynaFile : public CFile {
+ public:
+ CDynamide<fbSize,bSize>* m_Daddy;
+ CArray<LONG,LONG> m_Blocks;
+ LONG m_Position;
+
+ CDynaFile(CDynamide<fbSize,bSize>* daddy) : m_Daddy(NULL) { AttachToDaddy(daddy); }
+ virtual ~CDynaFile() { Close(); DetachFromDaddy(); }
+
+ void AttachToDaddy(CDynamide<fbSize,bSize>* daddy) {
+ ASSERT(!m_Daddy);
+ ASSERT(daddy);
+ m_Daddy=daddy;
+ m_Daddy->AttachDynaFile(this);
+ }
+ void DetachFromDaddy() {
+ ASSERT(m_Daddy);
+ ASSERT(!IsOpened());
+ m_Daddy->DetachDynaFile(this);
+ m_Daddy=NULL;
+ }
+
+ BOOL Create() {
+ if(IsOpened())
+ return FALSE;
+ m_Blocks.SetAtGrow(0,m_Daddy->Allocate());
+ ASSERT(m_Blocks[0]>=0);
+ m_Position=0;
+ return TRUE;
+ }
+ BOOL Open(LONG fb) {
+ if(IsOpened())
+ return FALSE;
+ ASSERT(fb>=0);
+ theBlock* b;
+ do{
+ m_Blocks.Add(fb);
+ b = m_Daddy->m_File->GetCached(fb);
+ ASSERT(b);
+ fb=b->next;
+ if(m_Blocks[m_Blocks.GetUpperBound()]==fb)
+ return FALSE;
+ }while(fb>=0);
+ m_Position=0;
+ return TRUE;
+ }
+
+ LONG GetFile() {
+ if(!IsOpened())
+ return -1;
+ return m_Blocks[0];
+ }
+ virtual DWORD GetPosition() const {
+ if(!IsOpened())
+ return 0;
+ if(m_Position<0)
+ return 0;
+ if(m_Position>GetLength())
+ return GetLength();
+ return m_Position;
+ }
+ virtual CString GetFileName() {
+ CString rv;
+ if(IsOpened())
+ rv.Format("0x%08lX",m_Blocks[0]);
+ else
+ rv.Format("None");
+ return rv;
+ }
+ virtual CString GetFileTitle() { return GetFileName(); }
+ virtual CString GetFilePath() { return GetFileName(); }
+ virtual void SetFilePath(LPCTSTR lpszNewName) { ASSERT(FALSE); }
+
+ virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL) { ASSERT(FALSE); return FALSE; }
+ virtual CFile* Duplicate() { ASSERT(FALSE); return NULL; }
+
+ virtual LONG Seek(LONG lOff, UINT nFrom) {
+ if(!IsOpened())
+ return -1;
+ switch(nFrom){
+ case CFile::begin:
+ m_Position=lOff;
+ break;
+ case CFile::current:
+ m_Position+=lOff;
+ break;
+ case CFile::end:
+ m_Position=GetLength()+lOff;
+ break;
+ default:
+ ASSERT(FALSE);
+ return -1;
+ }
+ if(m_Position<0)
+ m_Position=0;
+ if(m_Position>GetLength())
+ m_Position=GetLength();
+ return m_Position;
+ }
+ virtual void SetLength(DWORD dwNewLen) {
+ if(!IsOpened())
+ return;
+ if(dwNewLen<GetLength()){
+ dwNewLen=dwNewLen+sizeof(TheBlock.data);
+ dwNewLen-=dwNewLen%sizeof(TheBlock.data);
+ while(dwNewLen<GetLength() && m_Blocks.GetSize()>1){
+ LONG mb = m_Blocks[m_Blocks.GetUpperBound()];
+ LONG mb1 = m_Blocks[m_Blocks.GetUpperBound()-1];
+ theBlock* b = m_Daddy->m_File->GetCached(mb1);
+ ASSERT(b);
+ ASSERT(b->next==mb);
+ b->next=-1;
+ m_Daddy->m_File->MakeDirty(mb1);
+ m_Daddy->Deallocate(mb);
+ m_Blocks.SetSize(m_Blocks.GetSize()-1);
+ }
+ }else{
+ while(dwNewLen>GetLength()){
+ LONG mb = m_Blocks[m_Blocks.GetUpperBound()];
+ LONG newBlock = m_Daddy->Allocate();
+ ASSERT(newBlock>=0);
+ theBlock* b = m_Daddy->m_File->GetCached(mb);
+ ASSERT(b);
+ ASSERT(b->next<0);
+ b->next=newBlock;
+ m_Daddy->m_File->MakeDirty(mb);
+ m_Blocks.Add(newBlock);
+ }
+ }
+ }
+ virtual DWORD GetLength() const {
+ return ((long)m_Blocks.GetSize())*((long)sizeof(TheBlock.data));
+ }
+
+ virtual UINT Read(void* lpBuf, UINT nCount) {
+ UINT rv = 0;
+ ASSERT(m_Position>=0 && m_Position<=GetLength());
+ LPBYTE data = (LPBYTE)lpBuf;
+ while(nCount && m_Position<GetLength()){
+ UINT bn = m_Position/sizeof(TheBlock.data);
+ UINT bo = m_Position%sizeof(TheBlock.data);
+ theBlock* b = m_Daddy->m_File->GetCached(m_Blocks[bn]);
+ ASSERT(b);
+ UINT bc = min(nCount,sizeof(TheBlock.data)-bo);
+ memmove(data,&b->data[bo],bc);
+ nCount-=bc;
+ data=&data[bc];
+ rv+=bc;
+ m_Position+=bc;
+ }
+ return rv;
+ }
+ virtual void Write(const void* lpBuf, UINT nCount) {
+ ASSERT(m_Position>=0 && m_Position<=GetLength());
+ LPBYTE data = (LPBYTE)lpBuf;
+ while(nCount){
+ UINT bn = m_Position/sizeof(TheBlock.data);
+ UINT bo = m_Position%sizeof(TheBlock.data);
+ while(bn>=m_Blocks.GetSize()){
+ LONG mb = m_Blocks[m_Blocks.GetUpperBound()];
+ LONG newBlock = m_Daddy->Allocate();
+ ASSERT(newBlock>=0);
+ theBlock* b = m_Daddy->m_File->GetCached(mb);
+ ASSERT(b);
+ ASSERT(b->next<0);
+ b->next=newBlock;
+ m_Daddy->m_File->MakeDirty(mb);
+ m_Blocks.Add(newBlock);
+ }
+ theBlock* b = m_Daddy->m_File->GetCached(m_Blocks[bn]);
+ ASSERT(b);
+ UINT bc = min(nCount,sizeof(TheBlock.data)-bo);
+ memmove(&b->data[bo],data,bc);
+ m_Daddy->m_File->MakeDirty(m_Blocks[bn]);
+ nCount-=bc;
+ data=&data[bc];
+ m_Position+=bc;
+ }
+ }
+
+ virtual void LockRange(DWORD dwPos, DWORD dwCount) { ASSERT(FALSE); }
+ virtual void UnlockRange(DWORD dwPos, DWORD dwCount) { ASSERT(FALSE); }
+
+ virtual void Abort() { ASSERT(FALSE); }
+ virtual void Flush() {
+ m_Daddy->m_File->Flush();
+ }
+ virtual void Close() {
+ m_Blocks.RemoveAll();
+ }
+
+ BOOL IsOpened() const { return m_Blocks.GetSize()!=0; }
+ };
+
+ CDynaCache* m_File;
+ firstBlock m_FB;
+
+ CDynamide() : m_File(NULL) {}
+ ~CDynamide() { Close(); }
+
+ BOOL AttachDynaFile(CDynaFile* f) {
+ // ASSERT(!m_Files.Find(f));
+ // m_Files.AddHead(f);
+ return TRUE;
+ }
+ BOOL DetachDynaFile(CDynaFile* f) {
+ //POSITION p = m_Files.Find(f);
+ // ASSERT(p);
+ // m_Files.RemoveAt(p);
+ return TRUE;
+ }
+
+ BOOL Open(LPCTSTR file,BOOL bRO=FALSE) {
+ Close();
+ try{
+ CFile* f = new CFile(file,CFile::typeBinary|(bRO?CFile::modeRead|CFile::shareDenyWrite:CFile::modeReadWrite|CFile::shareDenyRead));
+ return Attach(f,TRUE);
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ }
+ BOOL Create(LPCTSTR file) {
+ Close();
+ try{
+ CFile* f = new CFile(file,CFile::typeBinary|CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyRead);
+ return Attach(f,TRUE);
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ }
+ BOOL Attach(CFile* file,BOOL bAutodelete=TRUE) {
+ if(IsOpened())
+ return FALSE;
+ m_File = new CDynaCache(file,bAutodelete);
+ if(!m_File->Read1stBlock(&m_FB)){
+ memset(&m_FB,0,sizeof(m_FB));
+ m_FB.freeFile=-1;
+ VERIFY(m_File->Write1stBlock(&m_FB));
+ }
+ return IsOpened();
+ }
+ // CFile* Detach();
+ BOOL Close() {
+ if(!IsOpened())
+ return FALSE;
+ m_File->Write1stBlock(&m_FB);
+ delete m_File;
+ m_File=NULL;
+ return TRUE;
+ }
+ BOOL IsOpened() {
+ return m_File != NULL;
+ }
+ BOOL Write1stBlock(void) {
+ if(!IsOpened())
+ return FALSE;
+ VERIFY(m_File->Write1stBlock(&m_FB));
+ return TRUE;
+ }
+
+ CDynaFile* CreateFile() {
+ CDynaFile* rv = new CDynaFile(this);
+ if(rv->Create())
+ return rv;
+ delete rv;
+ return NULL;
+ }
+ CDynaFile* OpenFile(LONG fb) {
+ CDynaFile* rv = new CDynaFile(this);
+ if(rv->Open(fb))
+ return rv;
+ delete rv;
+ return NULL;
+ }
+ BOOL DeleteFile(LONG fb) {
+ while(fb>=0){
+ theBlock* b = m_File->GetCached(fb);
+ LONG nb = b->next;
+ Deallocate(fb);
+ fb=nb;
+ }
+ return TRUE;
+ }
+
+ LONG Allocate() {
+ if(!IsOpened())
+ return -1;
+ if(m_FB.freeFile<0){
+ LONG rv = m_File->AllocateNode();
+ theBlock *b = m_File->GetCached(rv);
+ b->next=-1;
+ m_File->MakeDirty(rv);
+ return rv;
+ }
+ LONG rv = m_FB.freeFile;
+ theBlock *b = m_File->GetCached(rv);
+ m_FB.freeFile=b->next;
+ b->next=-1;
+ m_File->MakeDirty(rv);
+ m_File->Write1stBlock(&m_FB);
+ return rv;
+ }
+ BOOL Deallocate(LONG bk) {
+ if(!IsOpened())
+ return FALSE;
+ theBlock* b = m_File->GetCached(bk);
+ ASSERT(b);
+ if(m_FB.freeFile<0){
+ b->next=-1;
+ m_FB.freeFile=bk;
+ }else{
+ b->next=m_FB.freeFile;
+ m_FB.freeFile=bk;
+ }
+ m_File->MakeDirty(bk);
+ m_File->Write1stBlock(&m_FB);
+ return TRUE;
+ }
+};
+
+};
+
+#endif // __DYNAMIDE_H
diff --git a/shared-code/FindIFace.h b/shared-code/FindIFace.h
new file mode 100644
index 0000000..8dec8c4
--- a/dev/null
+++ b/shared-code/FindIFace.h
@@ -0,0 +1,125 @@
+#ifndef __FINDIFACE_H
+#define __FINDIFACE_H
+
+#include "SNMPeer.h"
+#include "SNMPExtDLL.h"
+#include "SNMPOIDs.h"
+
+namespace Klever {
+
+inline BOOL FindIFace(in_addr& target,in_addr& source)
+{
+DEFINE_OID(ipRouteDest, OIDipRouteDest);
+DEFINE_OID(ipRouteMask, OIDipRouteMask);
+DEFINE_OID(ipRouteIfIndex, OIDipRouteIfIndex);
+DEFINE_OID(ipRouteMetric1, OIDipRouteMetric1);
+DEFINE_OID(ipAdEntIfIndex, OIDipAdEntIfIndex);
+DEFINE_OID(ipAdEntAddr, OIDipAdEntAddr);
+struct _route {
+ int iface;
+ int metric;
+ DWORD nm;
+} routes[16];
+int nRoutes = 0;
+CSNMPVarBindList vbl;
+ vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteDest,sizeof(ipRouteDest))));
+ vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteMask,sizeof(ipRouteMask))));
+ vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteIfIndex,sizeof(ipRouteIfIndex))));
+ vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteMetric1,sizeof(ipRouteMetric1))));
+CSNMPExtDLL snmp("INETMIB1");
+ while(nRoutes<(sizeof(routes)/sizeof(routes[0]))){
+ if(
+ snmp.Request(CASNAny::typeASNGetNextRequest,vbl,vbl)
+ && vbl.GetCount() == 4
+ ){
+ POSITION p = vbl.GetHeadPosition();
+ _route r = {-1,-1};
+ in_addr d, m;
+ BOOL bD = FALSE, bM = FALSE;
+ while(p){
+ CSNMPVarBind& vb = vbl.GetNext(p);
+ if(
+ vb.IsName(ipRouteDest,sizeof(ipRouteDest))
+ && vb.value.type==CASNAny::typeASNIP
+ ){
+ d.s_addr=vb.value.value.ip.s_addr; bD = TRUE;
+ }else if(
+ vb.IsName(ipRouteMask,sizeof(ipRouteMask))
+ && vb.value.type==CASNAny::typeASNIP
+ ){
+ m.s_addr=vb.value.value.ip.s_addr; bM = TRUE;
+ }else if(
+ vb.IsName(ipRouteIfIndex,sizeof(ipRouteIfIndex))
+ && vb.value.type==CASNAny::typeASNInteger
+ ){
+ r.iface=vb.value.value.number;
+ }else if(
+ vb.IsName(ipRouteMetric1,sizeof(ipRouteMetric1))
+ && vb.value.type==CASNAny::typeASNInteger
+ ){
+ r.metric=vb.value.value.number;
+ }else
+ break;
+ }
+ if(r.iface<0 || r.metric<0 || (!bD) || (!bM))
+ break;
+ if((target.s_addr&m.s_addr)==(d.s_addr&m.s_addr)){
+ r.nm=htonl(m.s_addr);
+ memmove(&routes[nRoutes++],&r,sizeof(routes[0]));
+ }
+ }else
+ break;
+ }
+ if(!nRoutes)
+ return FALSE;
+int rn = 0;
+ if(nRoutes>1){
+ for(int tmp=1;tmp<nRoutes;tmp++)
+ if(
+ routes[tmp].metric<routes[rn].metric
+ || routes[tmp].nm>routes[rn].nm
+ )
+ rn = tmp;
+ }
+int iface = routes[rn].iface;
+ vbl.RemoveAll();
+ vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipAdEntAddr,sizeof(ipAdEntAddr))));
+ vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipAdEntIfIndex,sizeof(ipAdEntIfIndex))));
+ for(;;){
+ if(
+ snmp.Request(CASNAny::typeASNGetNextRequest,vbl,vbl)
+ && vbl.GetCount()==2
+ ){
+ in_addr a; a.s_addr = INADDR_NONE;
+ int ifn = -1;
+ POSITION p = vbl.GetHeadPosition();
+ while(p){
+ CSNMPVarBind& vb = vbl.GetNext(p);
+ if(
+ vb.IsName(ipAdEntAddr,sizeof(ipAdEntAddr))
+ && vb.value.type==CASNAny::typeASNIP
+ ){
+ a.s_addr=vb.value.value.ip.s_addr;
+ }else if(
+ vb.IsName(ipAdEntIfIndex,sizeof(ipAdEntIfIndex))
+ && vb.value.type==CASNAny::typeASNInteger
+ ){
+ ifn = vb.value.value.number;
+ }else
+ break;
+ }
+ if(ifn<0)
+ break;
+ if(ifn==iface){
+ source.s_addr=a.s_addr;
+ return TRUE;
+ }
+ }else
+ break;
+ }
+ return FALSE;
+}
+
+};
+
+#endif // __FINDIFACE_H
diff --git a/shared-code/LRUCache.h b/shared-code/LRUCache.h
new file mode 100644
index 0000000..569e829
--- a/dev/null
+++ b/shared-code/LRUCache.h
@@ -0,0 +1,113 @@
+#ifndef __LRUCACHE_H
+#define __LRUCACHE_H
+
+namespace Klever {
+
+template<class IDX,class ARGIDX,class DATA>
+class CLRUCache : public CObject {
+public:
+ struct CacheEntry {
+ enum cacheState {
+ cacheClean, cacheDirty, cacheEmpty
+ };
+ cacheState m_State;
+ UINT m_hits;
+
+ IDX m_idx;
+ DATA* m_pData;
+
+ CacheEntry() { m_State=cacheEmpty; VERIFY(m_pData=new DATA); m_hits=0; }
+ virtual ~CacheEntry() { delete m_pData; }
+ };
+ typedef CMap<IDX,ARGIDX,CacheEntry*,CacheEntry*> CCacheMap;
+ typedef CList<CacheEntry*,CacheEntry*> CCacheList;
+
+ CCacheList m_Cache;
+ CCacheMap m_Map;
+
+ CLRUCache(UINT cacheSize) {
+ for(int tmp=0;tmp<cacheSize;tmp++){
+ CacheEntry* p = new CacheEntry;
+ m_Cache.AddTail(p);
+ }
+ }
+ virtual ~CLRUCache() {
+ Flush();
+ POSITION p = m_Cache.GetHeadPosition();
+ while(p){
+ CacheEntry* c = m_Cache.GetNext(p);
+ delete c;
+ }
+ }
+
+ DATA* GetCached(ARGIDX idx,BOOL bLoad=TRUE) {
+ CacheEntry* rv;
+ if(m_Map.Lookup(idx,rv)){
+ rv->m_hits++;
+ PopUp(rv);
+ return rv->m_pData;
+ }
+ if(!bLoad)
+ return NULL;
+ rv = m_Cache.GetTail();
+ ASSERT(rv);
+ switch(rv->m_State){
+ case CacheEntry::cacheDirty:
+ FlushEntry(rv);
+ case CacheEntry::cacheClean:
+ m_Map.RemoveKey(rv->m_idx);
+ rv->m_State=CacheEntry::cacheEmpty;
+ case CacheEntry::cacheEmpty:
+ break;
+ default:
+ ASSERT(FALSE);
+ }
+ if(!_ReadIn(idx,rv->m_pData))
+ return NULL;
+ rv->m_hits=1;
+ rv->m_State=CacheEntry::cacheClean;
+ rv->m_idx=idx;
+ m_Map[idx]=rv;
+ PopUp(rv);
+ return rv->m_pData;
+ }
+ BOOL MakeDirty(ARGIDX idx) {
+ CacheEntry* pEntry;
+ if(m_Map.Lookup(idx,pEntry)){
+ ASSERT(pEntry->m_State==CacheEntry::cacheClean || pEntry->m_State==CacheEntry::cacheDirty);
+ pEntry->m_State=CacheEntry::cacheDirty;
+ return TRUE;
+ }
+ return FALSE;
+ }
+ BOOL Flush() {
+ POSITION p = m_Cache.GetHeadPosition();
+ while(p){
+ CacheEntry* pEntry = m_Cache.GetNext(p);
+ ASSERT(pEntry);
+ FlushEntry(pEntry);
+ }
+ return TRUE;
+ }
+ BOOL FlushEntry(CacheEntry* pEntry) {
+ if(pEntry->m_State==CacheEntry::cacheDirty){
+ BOOL rv = _WriteOut(pEntry->m_idx,pEntry->m_pData);
+ if(rv)
+ pEntry->m_State=CacheEntry::cacheClean;
+ }
+ return FALSE;
+ }
+ void PopUp(CacheEntry* pEntry) {
+ POSITION p = m_Cache.Find(pEntry);
+ ASSERT(p);
+ m_Cache.RemoveAt(p);
+ VERIFY(m_Cache.AddHead(pEntry));
+ }
+
+ virtual BOOL _ReadIn(ARGIDX idx,DATA* data) = 0;
+ virtual BOOL _WriteOut(ARGIDX idx,DATA* data) = 0;
+};
+
+};
+
+#endif // __LRUCACHE_H
diff --git a/shared-code/RegEx.cpp b/shared-code/RegEx.cpp
new file mode 100644
index 0000000..b7bab62
--- a/dev/null
+++ b/shared-code/RegEx.cpp
@@ -0,0 +1,1697 @@
+#include "../stdafx.h"
+#include "RegEx.h"
+
+#define isWordableChar(c) (isalnum(c) || (c)=='_')
+
+BOOL CRegEx::Compile(LPCTSTR regex,int flags)
+{
+ ASSERT(!((flags&regExtended) && (flags&regLiteral)));
+ m_Matches.RemoveAll();
+ m_Strip.RemoveAll();
+ m_Strip.SetSize(0,15);
+ m_Pattern=regex;
+ m_ParsePointer=0;
+ m_Error=0;
+ m_Sets.RemoveAll();
+ m_Flags=flags;
+ m_iFlags=0;
+ m_BOLs=m_EOLs=0;
+ m_Subexps = 0;
+ m_Categories=1; // 0 is 'everything else'
+ m_bBackRefs=FALSE;
+ memset(m_Category,0,sizeof(m_Category));
+
+ // Go ahead.
+ m_Error || m_Strip.Add(CSop(CSop::opEnd));
+ if(flags&regExtended){
+ ParseERE();
+ }else if(flags&regLiteral){
+ ParseLiteral();
+ }else{
+ ParseBRE();
+ }
+ m_Error || m_Strip.Add(CSop(CSop::opEnd));
+ Categorize();
+ m_Strip.FreeExtra();
+ FigureMust();
+ m_Pluses=CountPluses();
+ if(m_iFlags&iflagsBad){
+ m_Error || (m_Error=regeAssert);
+ // ??? point to nuls? ;-)
+ }
+ // We may wish to free some memory here if we're erroneous (ie. m_Error..)
+ m_ParseParens.RemoveAll();
+#ifdef _DEBUG
+ if(m_Error){
+ CString tmp;
+ tmp.Format("RE: ParseError: %d\n",m_Error);
+ TRACE0(tmp);
+ }
+// DumpStrip(afxDump);
+#endif
+ return (m_bCompiled=(!m_Error));
+}
+
+BOOL CRegEx::Match(LPCTSTR src,int flags)
+{
+ if(!m_bCompiled)
+ return FALSE;
+ if(m_iFlags&iflagsBad)
+ return FALSE;
+ m_Input=src;
+ m_mFlags=flags;
+ m_mPointer=m_Input;
+ m_mBegin=m_Input;
+ m_mEnd=&m_mBegin[m_Input.GetLength()];
+ ASSERT(m_mPointer<=m_mEnd);
+ m_Matches.RemoveAll();
+ if(!m_Must.IsEmpty()){
+ if(m_Input.Find(m_Must)<0)
+ return FALSE;
+ }
+ // Go ahead..
+int stripLen = m_Strip.GetSize();
+ m_mLastPos.SetSize(0);
+ for(int tmp=0;tmp<stripLen;tmp++)
+ m_Strip[tmp].m_MatchData=0;
+LPCTSTR beginp = m_mBegin;
+LPCTSTR endp;
+ for(;;){
+ endp = MatchFast(beginp);
+ if(!endp)
+ return FALSE;
+ if((m_mFlags&regNoSubExpressions) && !m_bBackRefs)
+ break;
+ ASSERT(m_cOldP);
+ for(;;){
+ endp = MatchSlow(m_cOldP,m_mEnd,1,stripLen-1);
+ if(endp)
+ break;
+ ASSERT(m_cOldP<m_mEnd);
+ m_cOldP++;
+ }
+ if((m_mFlags&regOneMatch) && !m_bBackRefs)
+ break;
+ // Oh, his, we want the subexpression..
+ m_Matches.SetSize(m_Subexps+1);
+ LPCTSTR dp;
+ if(!m_bBackRefs && !(m_mFlags&regBackRefs)){
+ dp = MatchDissect(m_cOldP,endp,1,stripLen-1);
+ }else{
+ if(m_Pluses>0 && !m_mLastPos.GetSize())
+ m_mLastPos.SetSize(m_Pluses);
+ dp = MatchBackRef(m_cOldP,endp,1,stripLen-1,0);
+ }
+ if(dp)
+ break;
+ // Uh.. oh.. we couldn't find a subexpression-level match
+ ASSERT(m_bBackRefs);
+ ASSERT(m_Pluses==0 || m_mLastPos.GetSize());
+ for(;;){
+ if(dp || endp <= m_cOldP)
+ break; // defeat.. ?
+ endp = MatchSlow(m_cOldP,endp-1,1,stripLen-1);
+ if(!endp)
+ break; // defeat.. ?
+ // Try it on a shorter possibility..
+#ifdef _DEBUG
+ for(tmp=1;tmp<=m_Subexps;tmp++)
+ ASSERT(m_Matches[tmp].m_Begin<0 && m_Matches[tmp].m_End<0);
+#endif
+ dp = MatchBackRef(m_cOldP,endp,1,stripLen-1,0);
+ }
+ ASSERT((!dp) || dp==endp);
+ if(dp) // Found a shorter one..
+ break;
+ // Despite initial appearances, there is no match here
+ beginp = m_cOldP+1;
+ ASSERT(beginp<=m_mEnd);
+ }
+ // Fill in the detail if so requested..
+ if(!(m_mFlags&regNoSubExpressions)){
+ if(!m_Matches.GetSize())
+ m_Matches.SetSize(1);
+ m_Matches[0].m_Begin=m_cOldP-m_mBegin;
+ m_Matches[0].m_End=endp-m_mBegin;
+ }
+ m_mLastPos.RemoveAll();
+ return TRUE;
+}
+
+CString CRegEx::Replace(LPCTSTR src,LPCTSTR rep,int flags)
+{
+ // ***
+ return CString();
+}
+
+void CRegEx::ParseERE(int stop)
+{
+UCHAR c;
+BOOL first=TRUE;
+int prevF, prevB;
+ for(;;){
+ int co = m_Strip.GetSize();
+ while(m_ParsePointer < m_Pattern.GetLength() && ((c=m_Pattern[m_ParsePointer])!='|') && c!=stop)
+ ParseEREexp();
+ if(m_Strip.GetSize()==co){
+ m_Error || (m_Error=regeEmpty);
+ // ??? point to nuls?
+ }
+ if(m_ParsePointer>=m_Pattern.GetLength() || m_Pattern[m_ParsePointer]!='|')
+ break;
+ else
+ m_ParsePointer++;
+ if(first){
+ StripInsert(co,CSop(CSop::opChoice0,m_Strip.GetSize()-co+1));
+ prevF = prevB = co;
+ first=FALSE;
+ }
+ m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-prevB));
+ prevB = m_Strip.GetSize()-1;
+ m_Error || (m_Strip[prevF].m_Operand=m_Strip.GetSize()-prevF);
+ prevF = m_Strip.GetSize();
+ m_Error || m_Strip.Add(CSop(CSop::opOr1,0)); // offset isn't really right.. very so..
+ }
+ if(!first){
+ m_Error || (m_Strip[prevF].m_Operand=m_Strip.GetSize()-prevF);
+ m_Error || m_Strip.Add(CSop(CSop::opChoice1,m_Strip.GetSize()-prevB));
+ }
+ ASSERT(m_ParsePointer >= m_Pattern.GetLength() || m_Pattern[m_ParsePointer]==stop);
+}
+
+void CRegEx::ParseEREexp()
+{
+ ASSERT(m_ParsePointer < m_Pattern.GetLength());
+UCHAR c = m_Pattern[m_ParsePointer++];
+int pos = m_Strip.GetSize();
+int subno;
+int count, count2;
+BOOL wascaret=FALSE;
+ switch(c){
+ case '(':
+ if(!(m_ParsePointer<m_Pattern.GetLength())){
+ TRACE0("RE: '(' at the end of the pattern\n");
+ if(!m_Error)
+ m_Error = regeParen;
+ // ??? point to nuls?
+ }
+ m_Subexps++;
+ subno=m_Subexps;
+ m_ParseParens.SetAtGrow(m_Subexps,CParenthesis(m_Strip.GetSize()));
+ m_Error || m_Strip.Add(CSop(CSop::opLeftParen,subno));
+ if(m_ParsePointer>=m_Pattern.GetLength() || m_Pattern[m_ParsePointer]!=')')
+ ParseERE(')');
+ VERIFY(m_ParseParens[m_Subexps].m_End = m_Strip.GetSize());
+ m_Error || m_Strip.Add(CSop(CSop::opRightParen,subno));
+ if(m_ParsePointer >= m_Pattern.GetLength() || m_Pattern[m_ParsePointer++]!=')'){
+ TRACE0("RE: No matching ')'\n");
+ if(!m_Error)
+ m_Error = regeParen;
+ // ??? point to nuls?
+ }
+ break;
+ case '^':
+ m_Error || m_Strip.Add(CSop(CSop::opBOL));
+ m_iFlags|=iflagsUseBOL;
+ m_BOLs++;
+ wascaret=TRUE;
+ break;
+ case '$':
+ m_Error || m_Strip.Add(CSop(CSop::opEOL));
+ m_iFlags|=iflagsUseEOL;
+ m_EOLs++;
+ break;
+ case '|':
+ TRACE0("RE: '|' outside of expression\n");
+ if(!m_Error)
+ m_Error = regeEmpty;
+ // ??? point to nuls?
+ break;
+ case '*':
+ case '+':
+ case '?':
+ TRACE0("RE: '*'/'+'/'?' with no previous expression\n");
+ if(!m_Error)
+ m_Error = regeBadRepeat;
+ // ??? point to nuls?
+ break;
+ case '.':
+ if(m_Flags&regNewLine)
+ EmitNonNewLineAny();
+ else
+ m_Error || m_Strip.Add(CSop(CSop::opAny));
+ break;
+ case '[':
+ ParseBracket();
+ break;
+ case '\\':
+ if(m_ParsePointer >= m_Pattern.GetLength()){
+ TRACE0("RE: '\\' at the end of the pattern\n");
+ if(!m_Error)
+ m_Error = regeEscape;
+ // ??? point to nuls?
+ }else{
+ c = m_Pattern[m_ParsePointer++];
+ EmitOrdinary(c);
+ }
+ break;
+ case '{':
+ if(m_ParsePointer >= m_Pattern.GetLength() || !isdigit(m_Pattern[m_ParsePointer])){
+ TRACE0("RE: '{' with no repeat count\n");
+ if(!m_Error)
+ m_Error = regeBadRepeat;
+ // ??? point to nuls?
+ }
+ // Fallthrough..
+ default:
+ EmitOrdinary(c);
+ break;
+ }
+ if(m_ParsePointer >= m_Pattern.GetLength())
+ return;
+ c = m_Pattern[m_ParsePointer];
+ // Call a '{' repetition if followed by a digit
+ if (!(c=='*' || c=='+' || c=='?' || ( c=='{' && (m_ParsePointer+1) < m_Pattern.GetLength() && isdigit(m_Pattern[m_ParsePointer+1])) ))
+ return; // No repetitor - done.
+ m_ParsePointer++;
+ if(wascaret){
+ TRACE0("RE: repetitive '^' detected\n");
+ if(!m_Error)
+ m_Error = regeBadRepeat;
+ // ??? point to nuls?
+ }
+ switch(c){
+ case '*': // Implemeted as +?
+ // + expression
+ StripInsert(pos,CSop(CSop::opPlus0,m_Strip.GetSize()-pos+1));
+ m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
+ // ? expression
+ StripInsert(pos,CSop(CSop::opQuest0,m_Strip.GetSize()-pos+1));
+ m_Error || m_Strip.Add(CSop(CSop::opQuest1,m_Strip.GetSize()-pos));
+ break;
+ case '+':
+ // + expression
+ StripInsert(pos,CSop(CSop::opPlus0,m_Strip.GetSize()-pos+1));
+ m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
+ break;
+ case '?':
+ // Kludge - emit y? as (y|) until subtle bug gets fixed :-)
+ StripInsert(pos,CSop(CSop::opChoice0,m_Strip.GetSize()-pos+1));
+ m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-pos));
+ m_Error || (m_Strip[pos].m_Operand=m_Strip.GetSize()-pos);
+ m_Error || m_Strip.Add(CSop(CSop::opOr1,1));
+ m_Error || m_Strip.Add(CSop(CSop::opChoice1,2));
+ break;
+ case '{':
+ count = ParseCount();
+ if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]==','){
+ m_ParsePointer++;
+ if(isdigit(m_Pattern[m_ParsePointer])){ // HHH Personally, I doubt it is always available
+ count2=ParseCount();
+ if(!(count<=count2)){
+ TRACE0("RE: Disbalanced counts in '{}' repeater\n");
+ m_Error || (m_Error=regeBadBrace);
+ // ??? point to nuls?
+ }
+ }else // Single number with comma
+ count2=256; // Infinity
+ }else // Single number
+ count2=count;
+ EmitRepeat(pos,count,count2);
+ if(m_ParsePointer >= m_Pattern.GetLength() || m_Pattern[m_ParsePointer]!='}'){
+ // No '}'..
+ TRACE0("RE: No immediately following '}' of '{' expression\n");
+ while(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]!='}')
+ m_ParsePointer++;
+ if(m_ParsePointer >= m_Pattern.GetLength()){
+ TRACE0("RE: No closing '}' found\n");
+ m_Error || (m_Error=regeBrace);
+ }else
+ m_Error || (m_Error=regeBadBrace);
+ // ??? point to nuls?
+ }else
+ m_ParsePointer++;
+ break;
+ }
+ if(m_ParsePointer >= m_Pattern.GetLength())
+ return;
+ c = m_Pattern[m_ParsePointer];
+ if(!(c=='*' || c=='+' || c=='?' || (c=='{' && (m_ParsePointer+1)<m_Pattern.GetLength() && isdigit(m_Pattern[m_ParsePointer+1]))))
+ return;
+ TRACE0("RE: Double repeater\n");
+ m_Error || (m_Error=regeBadRepeat);
+ // ??? point to nuls?
+}
+
+void CRegEx::StripInsert(int pos,CSop& sop)
+{
+ if(m_Error)
+ return;
+int sn = m_Strip.GetSize();
+ m_Strip.InsertAt(pos,sop);
+ for(int tmp=1;tmp<m_ParseParens.GetSize();tmp++){
+ if(m_ParseParens[tmp].m_Begin>=pos)
+ m_ParseParens[tmp].m_Begin++;
+ if(m_ParseParens[tmp].m_End>=pos)
+ m_ParseParens[tmp].m_End++;
+ }
+}
+
+void CRegEx::EmitOrdinary(UCHAR c)
+{
+ if(m_Flags&regIgnoreCase && isalpha(c) && (tolower(c) !=toupper(c))){
+ // Emit both cases
+ CString savePattern = m_Pattern;
+ int savePointer = m_ParsePointer;
+ m_Pattern=c;
+ m_Pattern+=']';
+ m_ParsePointer=0;
+ ParseBracket();
+ m_Pattern=savePattern;
+ m_ParsePointer=savePointer;
+ }else{
+ m_Error || m_Strip.Add(CSop(CSop::opChar,c));
+ if(!m_Category[(BYTE)c])
+ m_Category[(BYTE)c]=m_Categories++;
+ }
+}
+
+void CRegEx::EmitNonNewLineAny()
+{
+ // Kludges're going on and on..
+CString savePattern = m_Pattern;
+int savePointer = m_ParsePointer;
+ m_Pattern="^\n]";
+ m_ParsePointer=0;
+ ParseBracket();
+ m_Pattern=savePattern;
+ m_ParsePointer=savePointer;
+}
+
+int CRegEx::ParseCount()
+{
+BOOL nonEmpty=FALSE;
+int rv = 0;
+UCHAR c;
+ while(m_ParsePointer < m_Pattern.GetLength() && isdigit(c=m_Pattern[m_ParsePointer]) && rv <=255){
+ rv = rv*10 + c-'0';
+ nonEmpty=TRUE;
+ m_ParsePointer++;
+ }
+ if(rv>255 || !nonEmpty){
+ m_Error || (m_Error=regeBadBrace);
+ // ??? point to nuls?
+ }
+ return rv;
+}
+
+void CRegEx::ParseBracket()
+{
+ // Dept. of truly sickening special case kludges
+ if((m_ParsePointer+5) < m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,6).Compare("[:<]]")){
+ m_Error || m_Strip.Add(CSop(CSop::opBOW));
+ m_ParsePointer+=6;
+ return;
+ }
+ if((m_ParsePointer+5) < m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,6).Compare("[:>]]")){
+ m_Error || m_Strip.Add(CSop(CSop::opEOW));
+ m_ParsePointer+=6;
+ return;
+ }
+BOOL invert=TRUE;
+ if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='^')
+ m_ParsePointer++;
+ else
+ invert=FALSE;
+CSet cset;
+ if(m_ParsePointer < m_Pattern.GetLength()){
+ switch(m_Pattern[m_ParsePointer]){
+ case ']':
+ case '-':
+ cset.Add(m_Pattern[m_ParsePointer]);
+ m_ParsePointer++;
+ break;
+ }
+ }
+ while(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]!=']' && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("-]")))
+ ParseBracketTerm(cset);
+ if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='-'){
+ m_ParsePointer++;
+ cset.Add('-');
+ }
+ if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]==']')
+ m_ParsePointer++;
+ else{
+ m_Error || (m_Error=regeBracket);
+ // ??? point to nuls?
+ return;
+ }
+ if(m_Flags&regIgnoreCase){
+ for(int tmp=CSet::size-1;tmp>=0;tmp--){
+ if(cset.IsIn(tmp) && isalpha(tmp) && (toupper(tmp)!=tolower(tmp)))
+ cset.Add(isupper(tmp)?tolower(tmp):toupper(tmp));
+ }
+ /*
+ if(!cset->m_Multis.IsEmpty())
+ cset.CollatingCase();
+ */
+ }
+ if(invert){
+ for(int tmp=CSet::size-1;tmp>=0;tmp--)
+ if(cset.IsIn(tmp))
+ cset.Sub(tmp);
+ else
+ cset.Add(tmp);
+ if(m_Flags&regNewLine)
+ cset.Sub('\n');
+ /*
+ if(!cset.m_Multis.IsEmpty())
+ cset.CollatingInvert();
+ */
+ }
+UCHAR c = cset.GetOnly();
+ if(c){
+ EmitOrdinary(c);
+ }else
+ m_Error || m_Strip.Add(CSop(CSop::opAnyOf,StoreSet(cset)));
+}
+
+void CRegEx::CSet::Add(UCHAR c)
+{
+ m_Set[(BYTE)c]=TRUE;
+ m_Hash+=c;
+}
+
+BOOL CRegEx::CSet::IsIn(UCHAR c)
+{
+ return m_Set[(BYTE)c];
+}
+
+void CRegEx::CSet::Sub(UCHAR c)
+{
+ m_Set[(BYTE)c]=FALSE;
+ m_Hash-=c;
+}
+
+UCHAR CRegEx::CSet::GetOnly()
+{
+int rv = 0;
+UCHAR only = 0;
+ for(int tmp=0;tmp<size;tmp++){
+ rv+=m_Set[tmp]?(only=tmp,1):0;
+ }
+ return (rv==1)?only:0;
+}
+
+int CRegEx::StoreSet(CSet& cset)
+{
+ for(int tmp=0;tmp<m_Sets.GetSize();tmp++)
+ if(m_Sets[tmp]==cset)
+ return tmp;
+ return m_Sets.Add(cset);
+}
+
+void CRegEx::ParseBracketTerm(CSet& cset)
+{
+UCHAR c;
+ switch((m_ParsePointer<m_Pattern.GetLength())?m_Pattern[m_ParsePointer]:0){
+ case '[':
+ c = ((m_ParsePointer+1)<m_Pattern.GetLength())?m_Pattern[m_ParsePointer+1]:0;
+ break;
+ case '-':
+ m_Error || (m_Error=regeRange);
+ // ??? point to nuls?
+ return;
+ default:
+ c = 0;
+ break;
+ }
+ switch(c){
+ case ':': // Character class
+ m_ParsePointer+=2;
+ if(m_ParsePointer>=m_Pattern.GetLength()){
+ m_Error || (m_Error=regeBracket);
+ // ??? point to nuls?
+ }
+ c = m_Pattern[m_ParsePointer];
+ if(c== '-' || c==']'){
+ m_Error || (m_Error=regeCType);
+ // ??? point to nuls?
+ }
+ ParseBracketCClass(cset);
+ if(m_ParsePointer>=m_Pattern.GetLength()){
+ m_Error || (m_Error=regeBracket);
+ // ??? point to nuls?
+ }
+ if((m_ParsePointer+1)>=m_Pattern.GetLength() || (m_Pattern.Mid(m_ParsePointer,2).Compare(":]"))){
+ m_Error || (m_Error=regeCType);
+ // ??? point to nuls?
+ }else
+ m_ParsePointer+=2;
+ break;
+ case '=': // Equivalence class
+ m_ParsePointer+=2;
+ if(m_ParsePointer >= m_Pattern.GetLength()){
+ m_Error || (m_Error=regeBracket);
+ // ??? point to nuls?
+ }
+ c = m_Pattern[m_ParsePointer];
+ if(c== '-' || c==']'){
+ m_Error || (m_Error=regeCollate);
+ // ??? point to nuls?
+ }
+ ParseBracketEClass(cset);
+ if((m_ParsePointer+1)>=m_Pattern.GetLength() || (m_Pattern.Mid(m_ParsePointer,2).Compare("=]"))){
+ m_Error || (m_Error=regeCollate);
+ // ??? point to nuls?
+ }else
+ m_ParsePointer+=2;
+ break;
+ default: // Symbol, character or range
+ {
+ UCHAR start, finish;
+ start = ParseBracketSymbol();
+ if((m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='-') /*&& (m_ParsePointer+1)<m_Pattern.GetLength() && m_Pattern[m_ParsePointer+1]==']'*/){
+ // I believe the expression above is seetwo..
+ // range.
+ m_ParsePointer++;
+ if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='-'){
+ m_ParsePointer++;
+ finish='-';
+ }else
+ finish=ParseBracketSymbol();
+ }else
+ finish=start;
+ if(((BYTE)start)>((BYTE)finish)){
+ m_Error || (m_Error=regeRange);
+ // ??? point to nuls?
+ }
+ for(int tmp=start;tmp<=(BYTE)finish;tmp++)
+ cset.Add(tmp);
+ }
+ break;
+ }
+}
+
+void CRegEx::ParseBracketCClass(CSet& cset)
+{
+static struct {
+ char *className;
+ char *classChars;
+} cc[] = {
+ {"alnum","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
+ {"alpha","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
+ {"blank"," \t"},
+ {"cntrl","\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177"},
+ {"digit","0123456789"},
+ {"graph","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"},
+ {"lower","abcdefghijklmnopqrstuvwxyz"},
+ {"print","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ "},
+ {"punct","!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"},
+ {"space","\t\n\v\f\r "},
+ {"upper","ABCDEFGHIJKLMNOPQRSTUVWXYZ"},
+ {"xdigit","0123456789ABCDEFabcdef"}
+};
+CString cclass;
+UCHAR c;
+ while(m_ParsePointer < m_Pattern.GetLength() && isalpha(c=m_Pattern[m_ParsePointer])){
+ cclass+=c;
+ m_ParsePointer++;
+ }
+char *classChars = NULL;
+ for(int tmp=0;tmp<(sizeof(cc)/sizeof(cc[0]));tmp++){
+ if(!cclass.CompareNoCase(cc[tmp].className)){
+ classChars=cc[tmp].classChars;
+ break;
+ }
+ }
+ if(!classChars){
+ m_Error || (m_Error=regeCType);
+ // ??? point to nuls?
+ return;
+ }
+ while(*classChars)
+ cset.Add(*(classChars++));
+ // --- multis
+}
+
+void CRegEx::ParseBracketEClass(CSet& cset)
+{
+ cset.Add(ParseBracketCollatingElement('='));;
+}
+
+UCHAR CRegEx::ParseBracketCollatingElement(UCHAR term)
+{
+static struct {
+ char *entityName;
+ char entity;
+} cc[] = { {"NUL",'\0'},{"SOH",'\001'},{"STX",'\002'},{"ETX",'\003'},{"EOT",'\004'},{"ENQ",'\005'},{"ACK",'\006'},{"BEL",'\007'},{"alert",'\007'},{"BS",'\010'},{"backspace",'\b'},{"HT",'\011'},{"tab",'\t'},{"LF",'\012'},{"newline",'\n'},{"VT",'\013'},{"vertical-tab",'\v'},{"FF",'\014'},{"form-feed",'\f'},{"CR",'\015'},{"carriage-return",'\r'},{"SO",'\016'},{"SI",'\017'},{"DLE",'\020'},{"DC1",'\021'},{"DC2",'\022'},{"DC3",'\023'},{"DC4",'\024'},{"NAK",'\025'},{"SYN",'\026'},{"ETB",'\027'},{"CAN",'\030'},{"EM",'\031'},{"SUB",'\032'},{"ESC",'\033'},{"IS4",'\034'},{"FS",'\034'},{"IS3",'\035'},{"GS",'\035'},{"IS2",'\036'},{"RS",'\036'},{"IS1",'\037'},{"US",'\037'},{"space",' '},{"exclamation-mark",'!'},{"quotation-mark",'"'},{"number-sign",'#'},{"dollar-sign",'$'},{"percent-sign",'%'},{"ampersand",'&'},{"apostrophe",'\''},{"left-parenthesis",'('},{"right-parenthesis",')'},{"asterisk",'*'},{"plus-sign",'+'},{"comma",','},{"hyphen",'-'},{"hyphen-minus",'-'},{"period",'.'},{"full-stop",'.'},{"slash",'/'},{"solidus",'/'},{"zero",'0'},{"one",'1'},{"two",'2'},{"three",'3'},{"four",'4'},{"five",'5'},{"six",'6'},{"seven",'7'},{"eight",'8'},{"nine",'9'},{"colon",':'},{"semicolon",';'},{"less-than-sign",'<'},{"equals-sign",'='},{"greater-than-sign",'>'},{"question-mark",'?'},{"commercial-at",'@'},{"left-square-bracket",'['},{"backslash",'\\'},{"reverse-solidus",'\\'},{"right-square-bracket",']'},{"circumflex",'^'},{"circumflex-accent",'^'},{"underscore",'_'},{"low-line",'_'},{"grave-accent",'`'},{"left-brace",'{'},{"left-curly-bracket",'{'},{"vertical-line",'|'},{"right-brace",'}'},{"right-curly-bracket",'}'},{"tilde",'~'},{"DEL",'\177'} };
+CString seeTwo;
+ seeTwo=term;
+ seeTwo+=']';
+CString entityName;
+ while(m_ParsePointer<m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare(seeTwo)))
+ entityName+=m_Pattern[m_ParsePointer++];
+ if(m_ParsePointer>=m_Pattern.GetLength()){
+ m_Error || (m_Error=regeBracket);
+ // ??? point to nuls?
+ return 0;
+ }
+ for(int tmp=0;tmp<(sizeof(cc)/sizeof(cc[0]));tmp++)
+ if(!entityName.CompareNoCase(cc[tmp].entityName))
+ return cc[tmp].entity;
+ if(entityName.GetLength()==1)
+ return entityName[0];
+ m_Error || (m_Error=regeCollate);
+ // ??? point to nuls?
+ return 0;
+}
+
+UCHAR CRegEx::ParseBracketSymbol()
+{
+ if(m_ParsePointer>=m_Pattern.GetLength()){
+ m_Error || (m_Error=regeBracket);
+ // ??? point to nuls?
+ }
+ if((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("[."))
+ m_ParsePointer+=2;
+ else
+ return m_Pattern[m_ParsePointer++];
+ // Collating symbol
+UCHAR rv = ParseBracketCollatingElement('.');
+ if((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("[."))
+ m_ParsePointer+=2;
+ else{
+ m_Error || (m_Error=regeCollate);
+ // ??? point to nuls?
+ }
+ return rv;
+}
+
+void CRegEx::EmitRepeat(int pos,int from,int to)
+{
+ if(m_Error)
+ return;
+ ASSERT(from<=to);
+int finish = m_Strip.GetSize();
+int copy;
+#define N 2
+#define INF 3
+#define REP(f,t) ((f)*8+(t))
+#define MAP(n) (((n)<=1)?(n):((n)==256)?INF:N)
+ switch(REP(MAP(from),MAP(to))){
+ case REP(0,0): // must be user doing ths??
+ m_Strip.SetSize(pos);
+ break;
+ case REP(0,1): // as in '?'
+ case REP(0,N): // as in '{1,n}?'
+ case REP(0,INF): // as in '{1,}?'
+ // Kludge - emit y? as (y|) until something gets fixed..
+ StripInsert(pos,CSop(CSop::opChoice0,pos));
+ EmitRepeat(pos+1,1,to);
+ m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-pos));
+ m_Error || (m_Strip[pos].m_Operand=m_Strip.GetSize()-pos);
+ m_Error || m_Strip.Add(CSop(CSop::opOr1,1));
+ m_Error || m_Strip.Add(CSop(CSop::opChoice1,2));
+ break;
+ case REP(1,1):
+ break;
+ case REP(1,N): // as in 'x?x{1,n-1}'
+ // Kludge again..
+ StripInsert(pos,CSop(CSop::opChoice0,pos));
+ m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-pos));
+ m_Error || (m_Strip[pos].m_Operand=m_Strip.GetSize()-pos);
+ m_Error || m_Strip.Add(CSop(CSop::opOr1,1));
+ m_Error || m_Strip.Add(CSop(CSop::opChoice1,2));
+ copy = StripDuplicate(pos+1,finish+1);
+ ASSERT(copy==(finish+4));
+ EmitRepeat(copy,1,to-1);
+ break;
+ case REP(1,INF): // as in '+'
+ StripInsert(pos,CSop(CSop::opPlus0,pos));
+ m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
+ break;
+ case REP(N,N): // as in 'xx{from-1,to-1}'
+ copy = StripDuplicate(pos,finish);
+ EmitRepeat(copy,from-1,to-1);
+ break;
+ case REP(N,INF): // as in 'xx{n-1,}'
+ copy = StripDuplicate(pos,finish);
+ EmitRepeat(copy,from-1,to);
+ break;
+#ifndef NDEBUG
+ default:
+ ASSERT(FALSE);
+ break;
+#endif
+ }
+#undef MAP
+#undef REP
+#undef INF
+#undef N
+}
+
+int CRegEx::StripDuplicate(int from,int to)
+{
+int rv = m_Strip.GetSize();
+ ASSERT(from<=to);
+ if(from==to)
+ return rv;
+ // Maybe should be optimized for copying the whole thing.
+ for(int tmp=from;tmp<to;tmp++)
+ m_Strip.Add(m_Strip[tmp]);
+ return rv;
+}
+
+void CRegEx::Categorize()
+{
+ if(m_Error)
+ return;
+ for(int tmp=0;tmp<(sizeof(m_Category)/sizeof(m_Category[0]));tmp++)
+ if((!m_Category[tmp]) && IsInSets(tmp)){
+ int cat = m_Categories++;
+ m_Category[tmp]=cat;
+ for(int c=tmp+1;c<(sizeof(m_Category)/sizeof(m_Category[0]));c++)
+ if((!m_Category[c]) && IsInSameSets(tmp,c))
+ m_Category[c]=cat;
+ }
+}
+
+BOOL CRegEx::IsInSets(UCHAR c)
+{
+ for(int tmp=0;tmp<m_Sets.GetSize();tmp++)
+ if(m_Sets[tmp].IsIn(c))
+ return TRUE;
+ return FALSE;
+}
+
+BOOL CRegEx::IsInSameSets(UCHAR c1,UCHAR c2)
+{
+ for(int tmp=0;tmp<m_Sets.GetSize();tmp++)
+ if(m_Sets[tmp].IsIn(c1)!=m_Sets[tmp].IsIn(c2))
+ return FALSE;
+ return TRUE;
+}
+
+void CRegEx::FigureMust()
+{
+ if(m_Error)
+ return;
+ m_Must.Empty();
+int stripLen = m_Strip.GetSize();
+int seqStart, seqLength = 0;
+int mustStart, mustLength = 0;
+ for(int tmp=1;tmp<stripLen;tmp++){
+ switch(m_Strip[tmp].m_Operator){
+ case CSop::opChar:
+ if(!seqLength)
+ seqStart=tmp;
+ seqLength++;
+ break;
+ case CSop::opPlus0:
+ case CSop::opLeftParen:
+ case CSop::opRightParen:
+ break; // Break, since they don't break the sequence
+ case CSop::opQuest0:
+ case CSop::opChoice0:
+ // These ones we skip.
+ do{
+ tmp+=m_Strip[tmp].m_Operand;
+ // I still think it could be ASSERTed..
+ if(m_Strip[tmp].m_Operator!=CSop::opQuest1 && m_Strip[tmp].m_Operator!=CSop::opChoice1 && m_Strip[tmp].m_Operator!=CSop::opOr1){
+ m_iFlags|=iflagsBad;
+ return;
+ }
+ }while(m_Strip[tmp].m_Operator!=CSop::opQuest1 && m_Strip[tmp].m_Operator!=CSop::opChoice1);
+ // Fallthrough..
+ default:
+ // End of sequence
+ if(seqLength>mustLength){
+ mustStart=seqStart;
+ mustLength=seqLength;
+ }
+ seqLength=0;
+ break;
+ }
+ } // Hmm.. originally it's meant to be do while not opEnd..
+ if(!mustLength)
+ return;
+ // Turn into string, but, wait, personally I'm sure it could be put in the main loop.. or maybe not..
+ for(tmp=0;tmp<seqLength;tmp++){
+ while(m_Strip[seqStart+tmp].m_Operator!=CSop::opChar)
+ ASSERT(tmp<seqLength);
+ m_Must+=m_Strip[tmp].m_Operand;
+ }
+}
+
+int CRegEx::CountPluses()
+{
+ if(m_Error)
+ return 0;
+int stripLen = m_Strip.GetSize();
+int rv = 0;
+int nest = 0;
+ for(int tmp=0;tmp<stripLen;tmp++){
+ switch(m_Strip[tmp].m_Operator){
+ case CSop::opPlus0:
+ nest++;
+ break;
+ case CSop::opPlus1:
+ if(nest>rv)
+ rv = nest;
+ nest--;
+ break;
+ }
+ } // Again, originally we were supposed to scan till opEnd..
+ if(nest)
+ m_iFlags|=iflagsBad; // Could this be an ASSERTion?
+ return rv;
+}
+
+void CRegEx::ParseLiteral()
+{
+ if(!m_Pattern.GetLength()){
+ m_Error || (m_Error=regeEmpty);
+ // ??? point to nuls?
+ }
+ while(m_ParsePointer < m_Pattern.GetLength())
+ EmitOrdinary(m_Pattern[m_ParsePointer++]);
+}
+
+void CRegEx::ParseBRE(int stopa,int stopb)
+{
+int start = m_Strip.GetSize();
+BOOL first=TRUE;
+BOOL wasDollar=FALSE;
+ if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='^'){
+ m_ParsePointer++;
+ m_Error || m_Strip.Add(CSop(CSop::opBOL,0));
+ m_iFlags|=iflagsUseBOL;
+ m_BOLs++;
+ }
+CString stopstr;
+ if(stopa){
+ stopstr+=stopa;
+ if(stopb)
+ stopstr+=stopb;
+ }
+ while(m_ParsePointer < m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare(stopstr))){
+ wasDollar = ParseBREexp(first);
+ first=FALSE;
+ }
+ if(wasDollar){ // Trailing anchor that was..
+ m_Strip.SetSize(m_Strip.GetSize()-1);
+ m_Error || m_Strip.Add(CSop(CSop::opEOL,0));
+ m_iFlags|=iflagsUseEOL;
+ m_EOLs++;
+ }
+ if(m_Strip.GetSize()==start){
+ m_Error || (m_Error=regeEmpty);
+ // ??? point to nuls?
+ }
+}
+
+BOOL CRegEx::ParseBREexp(BOOL ordinaryStar)
+{
+int subno;
+int pos = m_Strip.GetSize();
+ ASSERT(m_ParsePointer<m_Pattern.GetLength());
+int c = m_Pattern[m_ParsePointer++];
+ if(c=='\\'){
+ if(m_ParsePointer>=m_Pattern.GetLength()){
+ m_Error || (m_Error=regeEscape);
+ // ??? point to nuls
+ }else
+ c = 0x100|m_Pattern[m_ParsePointer++];
+ }
+ switch(c){
+ case '.':
+ if(m_Flags&regNewLine)
+ EmitNonNewLineAny();
+ else
+ m_Error || m_Strip.Add(CSop(CSop::opAny,0));
+ break;
+ case '[':
+ ParseBracket();
+ break;
+ case 0x100|'{':
+ m_Error || (m_Error=regeBadRepeat);
+ // ??? point to nuls?
+ break;
+ case 0x100|'(':
+ m_Subexps++;
+ subno=m_Subexps;
+ m_ParseParens.SetAtGrow(m_Subexps,CParenthesis(m_Strip.GetSize()));
+ m_Error || m_Strip.Add(CSop(CSop::opLeftParen,subno));
+ if(m_ParsePointer<m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\)")))
+ ParseBRE('\\',')');
+ VERIFY(m_ParseParens[m_Subexps].m_End = m_Strip.GetSize());
+ m_Error || m_Strip.Add(CSop(CSop::opRightParen,subno));
+ if((m_ParsePointer+1) < m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\)"))
+ m_ParsePointer+=2;
+ else{
+ m_Error || (m_Error=regeParen);
+ // ??? point to nuls?
+ }
+ break;
+ case 0x100|')':
+ case 0x100|'}':
+ // Can this possibly happen?!
+ m_Error || (m_Error=regeParen);
+ // ??? point to nuls?
+ break;
+ case 0x100|'1':
+ case 0x100|'2':
+ case 0x100|'3':
+ case 0x100|'4':
+ case 0x100|'5':
+ case 0x100|'6':
+ case 0x100|'7':
+ case 0x100|'8':
+ case 0x100|'9':
+ {
+ int i = (c&0xFF)-'0';
+ if(i < m_ParseParens.GetSize() && m_ParseParens[i].m_End){
+ m_Error || m_Strip.Add(CSop(CSop::opBackRef0,i));
+ ASSERT(m_ParseParens[i].m_Begin);
+ ASSERT(m_Strip[m_ParseParens[i].m_Begin].m_Operator==CSop::opLeftParen);
+ ASSERT(m_Strip[m_ParseParens[i].m_End].m_Operator==CSop::opRightParen);
+ StripDuplicate(m_ParseParens[i].m_Begin+1,m_ParseParens[i].m_End);
+ m_Error || m_Strip.Add(CSop(CSop::opBackRef1,i));
+ }else{
+ m_Error || (m_Error=regeSubReg);
+ // ??? point to nuls?
+ }
+ m_bBackRefs=TRUE;
+ }
+ break;
+ case '*':
+ if(!ordinaryStar){
+ m_Error || (m_Error=regeBadRepeat);
+ // ??? point to nuls?
+ }
+ // Fallthrough..
+ default:
+ EmitOrdinary(c&0xFF);
+ break;
+ }
+ if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='*'){
+ m_ParsePointer++;
+ // as in '+?'
+ StripInsert(pos,CSop(CSop::opPlus0,m_Strip.GetSize()-pos+1));
+ m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
+ StripInsert(pos,CSop(CSop::opQuest0,m_Strip.GetSize()-pos+1));
+ m_Error || m_Strip.Add(CSop(CSop::opQuest1,m_Strip.GetSize()-pos));
+ }else if ((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\{")){
+ m_ParsePointer+=2;
+ int count = ParseCount();
+ int count2;
+ if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]==','){
+ m_ParsePointer++;
+ if(m_ParsePointer<m_Pattern.GetLength() && isdigit(m_Pattern[m_ParsePointer])){
+ count2=ParseCount();
+ if(count>count2){
+ m_Error || (m_Error=regeBadBrace);
+ // ??? poin to nuls?
+ }
+ }else // Single number with comma
+ count2=256;
+ }else // Single number
+ count2=count;
+ EmitRepeat(pos,count,count2);
+ if((m_ParsePointer+1)>=m_Pattern.GetLength() || m_Pattern.Mid(m_ParsePointer,2).Compare("\\}")){
+ while(m_ParsePointer<m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\}")))
+ m_ParsePointer++;
+ if(m_ParsePointer>=m_Pattern.GetLength()){
+ m_Error || (m_Error=regeBrace);
+ // ??? point to nuls?
+ }
+ m_Error || (m_Error=regeBadBrace);
+ }else
+ m_ParsePointer+=2;
+ }else if(c=='$')
+ return TRUE;
+ return FALSE;
+}
+
+CRegEx::CRegEx()
+{
+ m_bCompiled=FALSE;
+}
+
+LPCTSTR CRegEx::MatchFast(LPCTSTR begin)
+{
+ MatchStatesClear(CSop::stCurrent);
+ m_Strip[1].m_MatchData|=CSop::stCurrent;
+int stripLen = m_Strip.GetSize();
+ MatchStep(1,stripLen-1,CSop::stCurrent,charNothing,CSop::stCurrent);
+ MatchStatesCopy(CSop::stFresh,CSop::stCurrent);
+LPCTSTR coldp = NULL;
+LPCTSTR p = begin;
+int c = (begin==m_mBegin)?charOut:((int)(BYTE)m_mPointer[-1]);
+ for(;;){
+ // next character..
+ int lastc = c;
+ c = (p==m_mEnd)?charOut:(int)*(BYTE*)p;
+ if(MatchStatesEqual(CSop::stCurrent,CSop::stFresh))
+ coldp=p;
+ // Is there an EOL and/or BOL between lastc and c? - they ask..
+ int flagc=0;
+ int i = 0;
+ if((lastc=='\n' && m_Flags&regNewLine) || (lastc==charOut && !(m_mFlags&regNotBOL))){
+ flagc=charBOL;
+ i=m_BOLs;
+ }
+ if((c=='\n' && m_Flags&regNewLine) || (c==charOut && !(m_mFlags&regNotEOL))){
+ flagc=(flagc==charBOL)?charBOLEOL:charEOL;
+ i+=m_EOLs;
+ }
+ if(i){
+ for(;i>0;i--)
+ MatchStep(1,stripLen-1,CSop::stCurrent,flagc,CSop::stCurrent);
+ }
+ // What about a word boundary? - they wonder..
+ if((flagc==charBOL || (lastc!=charOut && !isWordableChar(c))) && (c!=charOut && isWordableChar(c)))
+ flagc = charBOW;
+ if((lastc!=charOut && isWordableChar(lastc)) && (flagc==charEOL || (c!=charOut && !isWordableChar(c))))
+ flagc = charEOW;
+ if(flagc==charBOW || flagc==charEOW){
+ MatchStep(1,stripLen-1,CSop::stCurrent,flagc,CSop::stCurrent);
+ }
+ // Are we done? Now WE wonder..
+ if((m_Strip[stripLen-1].m_MatchData&CSop::stCurrent) || p==m_mEnd)
+ break; // They insist I need to note break out.. Okay, I do..
+ // Nope, we're not done. We have to face this character..
+ MatchStatesCopy(CSop::stTemp,CSop::stCurrent);
+ MatchStatesCopy(CSop::stCurrent,CSop::stFresh);
+ ASSERT(c!=charOut);
+ MatchStep(1,stripLen-1,CSop::stTemp,c,CSop::stCurrent);
+ p++;
+ }
+ ASSERT(coldp);
+ m_cOldP=coldp; // *** I believe this variable can be changed 'in-place'
+ if(m_Strip[stripLen-1].m_MatchData&CSop::stCurrent)
+ return &p[1];
+ else
+ return NULL;
+}
+
+void CRegEx::MatchStatesClear(BYTE mask)
+{
+int stripLen = m_Strip.GetSize();
+ for(int tmp=0;tmp<stripLen;tmp++)
+ m_Strip[tmp].m_MatchData&=~mask;
+}
+
+void CRegEx::MatchStep(int from,int to,BYTE maskBefore,int charCode,BYTE maskAfter)
+{
+BOOL i;
+int look;
+int here = from;
+ for(int pc=from;pc!=to;pc++,here++){
+ CSop s=m_Strip[pc];
+ switch(s.m_Operator){
+ case CSop::opEnd:
+ ASSERT(pc==(to-1));
+ break;
+ case CSop::opChar:
+ // Only characters can match..
+ ASSERT((charCode<charOut) || charCode!=s.m_Operand);
+ if(charCode==s.m_Operand)
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opBOL:
+ if(charCode==charBOL || charCode==charBOLEOL)
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opEOL:
+ if(charCode==charEOL || charCode==charBOLEOL)
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opBOW:
+ if(charCode==charBOW)
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opEOW:
+ if(charCode==charEOW)
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opAny:
+ if(charCode<charOut)
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opAnyOf:
+ if(charCode<charOut && m_Sets[s.m_Operand].m_Set[charCode])
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
+ break;
+ case CSop::opBackRef0: // Ignored here..
+ case CSop::opBackRef1:
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+ case CSop::opPlus0:
+ // Forward, this is just an empty, comment says..
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+ case CSop::opPlus1:
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ i =(m_Strip[here-s.m_Operand].m_MatchData&maskAfter)!=0;
+ m_Strip[here-s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ if(!i && (m_Strip[here-s.m_Operand].m_MatchData&maskAfter)){
+ // oho, must reconsider loop body, comment says.. what's so 'oho' about it?
+ pc-=s.m_Operand+1;
+ here=pc;
+ }
+ break;
+ case CSop::opQuest0:
+ // two branches, both forward..
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ m_Strip[here+s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+ case CSop::opQuest1:
+ // just an empty.. aren't we tired of justanempties?
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+ case CSop::opLeftParen: // they say it's not significan there..
+ case CSop::opRightParen:
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+ case CSop::opChoice0: // mark the first two branches..
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ ASSERT(m_Strip[pc+s.m_Operand].m_Operator==CSop::opOr1);
+ m_Strip[here+s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+ case CSop::opOr0: // done a branch, find the end of choice..
+ if(m_Strip[here].m_MatchData&maskAfter){
+ for(look=1;(s=m_Strip[pc+look]).m_Operator!=CSop::opChoice1;look+=s.m_Operand)
+ ASSERT(s.m_Operator==CSop::opOr1);
+ m_Strip[here+look].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ }
+ break;
+ case CSop::opOr1: // Propagate Choice's marking..
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ if(m_Strip[pc+s.m_Operand].m_Operator!=CSop::opChoice1){
+ ASSERT(m_Strip[pc+s.m_Operand].m_Operator==CSop::opOr1);
+ m_Strip[here+s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ }
+ break;
+ case CSop::opChoice1: // Just empty.. :-)..
+ m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
+ break;
+#ifdef _DEBUG
+ default:
+ ASSERT(FALSE);
+ break;
+#endif
+ }
+ }
+}
+
+void CRegEx::MatchStatesCopy(BYTE dst,BYTE src)
+{
+int stripLen = m_Strip.GetSize();
+ for(int tmp=0;tmp<stripLen;tmp++){
+ // I believe this can be optimized, easily..
+ m_Strip[tmp].m_MatchData&=~dst;
+ m_Strip[tmp].m_MatchData|=(m_Strip[tmp].m_MatchData&src)?dst:0;
+ }
+}
+
+BOOL CRegEx::MatchStatesEqual(BYTE m1,BYTE m2)
+{
+int stripLen = m_Strip.GetSize();
+ for(int tmp=0;tmp<stripLen;tmp++){
+ BYTE mm = m_Strip[tmp].m_MatchData;
+ if(((mm&m1) && (mm&m2)) || !(mm&(m1|m2)))
+ continue;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+LPCTSTR CRegEx::MatchSlow(LPCTSTR begin,LPCTSTR end,int from,int to)
+{
+ MatchStatesClear(CSop::stCurrent);
+ m_Strip[from].m_MatchData|=CSop::stCurrent;
+ MatchStep(from,to,CSop::stCurrent,charNothing,CSop::stCurrent);
+LPCTSTR mp = NULL;
+int c = (m_mBegin==m_mPointer)?charOut:(int)(BYTE)begin[-1];
+LPCTSTR p = begin;
+ for(;;){
+ // next character..
+ int lastc = c;
+ c = (p==m_mEnd)?charOut:(int)*(BYTE*)p;
+ // Now we start to wonder if there is an EOL and/or BOL between lastc and c
+ int flagc = 0;
+ int i = 0;
+ if((lastc=='\n' && m_Flags&regNewLine) || (lastc==charOut && !(m_mFlags&regNotBOL))){
+ flagc = charBOL;
+ i = m_BOLs;
+ }
+ if((c=='\n' && m_Flags&regNewLine) || (c==charOut && !(m_mFlags&regNotEOL))){
+ flagc = (flagc==charBOL)?charBOLEOL:charEOL;
+ i+=m_EOLs;
+ }
+ if(i){
+ for(;i>0;i--)
+ MatchStep(from,to,CSop::stCurrent,flagc,CSop::stCurrent);
+ }
+ // Now we wonder about word boundaries..
+ if((flagc==charBOL || (lastc!=charOut && !isWordableChar(lastc))) && (c!=charOut && isWordableChar(c)))
+ flagc=charBOW;
+ if((lastc!=charOut && isWordableChar(lastc)) && (flagc==charEOL || (c!=charOut && !isWordableChar(c))))
+ flagc=charEOW;
+ if(flagc==charBOW || flagc==charEOW){
+ MatchStep(from,to,CSop::stCurrent,flagc,CSop::stCurrent);
+ }
+ // Are we done we all wonder??
+ if(m_Strip[to].m_MatchData&CSop::stCurrent)
+ mp=p;
+ if(MatchStatesEqual(CSop::stCurrent,CSop::stEmpty) || p==end)
+ break; // Again, we're obliged to note break out. We do.
+ // Sucks.. we have to face this character..
+ MatchStatesCopy(CSop::stTemp,CSop::stCurrent);
+ MatchStatesCopy(CSop::stCurrent,CSop::stEmpty);
+ ASSERT(c!=charOut);
+ MatchStep(from,to,CSop::stTemp,c,CSop::stCurrent);
+ MatchStep(from,to,CSop::stCurrent,charNothing,CSop::stCurrent);
+ p++;
+ }
+ return mp;
+}
+
+LPCTSTR CRegEx::MatchDissect(LPCTSTR begin,LPCTSTR end,int from,int to)
+{
+LPCTSTR sp = begin, dp;
+LPCTSTR stp, rest, tail, ssp, oldssp, sep;
+int ssub, esub;
+int es;
+int i;
+ for(int ss=from;ss<to;ss = es){
+ // Identify end of SubRE
+ es = ss;
+ switch(m_Strip[es].m_Operator){
+ case CSop::opPlus0:
+ case CSop::opQuest0:
+ es+=m_Strip[es].m_Operand;
+ break;
+ case CSop::opChoice0:
+ while(m_Strip[es].m_Operator!=CSop::opChoice1)
+ es+=m_Strip[es].m_Operand;
+ break;
+ }
+ es++;
+ // Figure out what it matched
+ switch(m_Strip[ss].m_Operator){
+ case CSop::opEnd:
+ ASSERT(FALSE);
+ break;
+ case CSop::opChar:
+ sp++;
+ break;
+ case CSop::opBOL:
+ case CSop::opEOL:
+ case CSop::opBOW:
+ case CSop::opEOW:
+ break;
+ case CSop::opAny:
+ case CSop::opAnyOf:
+ sp++;
+ break;
+ case CSop::opBackRef0:
+ case CSop::opBackRef1:
+ ASSERT(FALSE);
+ break;
+ // Cases where lenght of match is hard to find..
+ case CSop::opQuest0:
+ stp=end;
+ for(;;){
+ // How long could this one be??
+ rest = MatchSlow(sp,stp,ss,es);
+ ASSERT(rest); // It did match.. It should've..
+ // Could the rest match the rest? (good question)
+ tail = MatchSlow(rest,end,es,to);
+ if(tail==end)
+ break; // yup.
+ // nope, try a shorter match for this one..
+ stp=rest-1;
+ ASSERT(stp>=sp); // It did work.. It should've..
+ }
+ ssub=ss+1;
+ esub=es-1;
+ // Did innards match?
+ if(MatchSlow(sp,rest,ssub,esub)){
+ dp = MatchDissect(sp,rest,ssub,esub);
+ ASSERT(dp==rest);
+ }else // nope..
+ ASSERT(sp==rest);
+ sp = rest;
+ break;
+ case CSop::opPlus0:
+ stp=end;
+ for(;;){
+ // How long could this one be??
+ rest = MatchSlow(sp,stp,ss,es);
+ ASSERT(rest); // It did.. It should've..
+ // Could the rest match the rest?
+ tail = MatchSlow(rest,end,es,to);
+ if(tail==end)
+ break; // yup.
+ // nope..
+ stp=rest-1;
+ ASSERT(stp>=sp); // It should've worked, we believe..
+ }
+ ssub=ss+1;
+ esub=es-1;
+ ssp=sp;
+ oldssp=ssp;
+ for(;;){ // Find last match of innards..
+ sep = MatchSlow(ssp,rest,ssub,esub);
+ if((!sep) || sep==ssp)
+ break; // Failed or matched nothin'
+ oldssp=ssp;
+ ssp=sep;
+ }
+ if(!sep){
+ // Last successfull..
+ sep=ssp;
+ ssp=oldssp;
+ }
+ ASSERT(sep=rest); // Must exhaust substring they say..
+ VERIFY(MatchSlow(ssp,sep,ssub,esub)==rest); // Assert or verify - that is the question..
+ dp = MatchDissect(ssp,sep,ssub,esub);
+ ASSERT(dp==sep);
+ sp=rest;
+ break;
+ case CSop::opChoice0:
+ stp = end;
+ for(;;){
+ // how long..
+ rest = MatchSlow(sp,stp,ss,es);
+ ASSERT(rest);
+ // Could it..
+ tail = MatchSlow(rest,end,es,to);
+ if(tail==end)
+ break; // y
+ // n
+ stp = rest-1;
+ ASSERT(stp>=sp);
+ }
+ ssub=ss+1;
+ esub=ss+m_Strip[ss].m_Operand-1;
+ ASSERT(m_Strip[esub].m_Operator==CSop::opOr0);
+ for(;;){ // Find first matching branch..
+ if(MatchSlow(sp,rest,ssub,esub)==rest)
+ break;
+ // this one missed, try next..
+ ASSERT(m_Strip[esub].m_Operator==CSop::opOr0);
+ esub++;
+ ASSERT(m_Strip[esub].m_Operator==CSop::opOr1);
+ ssub=esub+1;
+ esub+=m_Strip[esub].m_Operand;
+ if(m_Strip[esub].m_Operator==CSop::opOr1)
+ esub--;
+ else
+ ASSERT(m_Strip[esub].m_Operator==CSop::opChoice1);
+ }
+ dp = MatchDissect(sp,rest,ssub,esub);
+ ASSERT(dp==rest);
+ sp=rest;
+ break;
+ case CSop::opPlus1:
+ case CSop::opQuest1:
+ case CSop::opOr0:
+ case CSop::opOr1:
+ case CSop::opChoice1:
+ ASSERT(FALSE);
+ break;
+ case CSop::opLeftParen:
+ i = m_Strip[ss].m_Operand;
+ ASSERT(0<i && i<=m_Subexps);
+ m_Matches[i].m_Begin=sp-m_mBegin;
+ break;
+ case CSop::opRightParen:
+ i = m_Strip[ss].m_Operand;
+ ASSERT(0<i && i<=m_Subexps);
+ m_Matches[i].m_End=sp-m_mBegin;
+ break;
+#ifdef _DEBUG
+ default: // Uh.. oh..
+ ASSERT(FALSE);
+ break;
+#endif
+ }
+ }
+ ASSERT(sp==end);
+ return sp;
+}
+
+LPCTSTR CRegEx::MatchBackRef(LPCTSTR begin,LPCTSTR end,int from,int to,int level)
+{
+LPCTSTR sp = begin;
+BOOL hard = FALSE;
+ // Get as far as we can as long as it's easy
+ for(int ss=from;!hard && ss<to;ss++){
+ CSop s = m_Strip[ss];
+ switch(s.m_Operator){
+ case CSop::opChar:
+ if(sp==end || *sp++ != s.m_Operand)
+ return NULL;
+ break;
+ case CSop::opAny:
+ if(sp==end)
+ return NULL;
+ sp++; // I'm sure this ++ could be embedded in previous expression..
+ break;
+ case CSop::opAnyOf:
+ if(sp==end || !m_Sets[s.m_Operand].IsIn(*sp++))
+ return NULL;
+ break;
+ case CSop::opBOL:
+ if(!((sp==m_mBegin && !(m_mFlags&regNotBOL)) || (sp<m_mEnd && *(sp-1)=='\n' && (m_Flags&regNewLine))))
+ return NULL;
+ break;
+ case CSop::opEOL:
+ if(!((sp==m_mEnd && !(m_mFlags&regNotEOL)) || (sp<m_mEnd && *sp=='\n' && (m_Flags&regNewLine))))
+ return NULL;
+ break;
+ case CSop::opBOW:
+ if(!(((sp==m_mBegin && !(m_mFlags&regNotBOL)) || (sp<m_mEnd && *(sp-1)=='\n' && (m_Flags&regNewLine)) || (sp>m_mBegin && !isWordableChar(*(sp-1)))) && (sp<m_mEnd && isWordableChar(*sp))))
+ return NULL;
+ break;
+ case CSop::opEOW:
+ if(!(((sp==m_mEnd && !(m_mFlags&regNotEOL)) || (sp<m_mEnd && *sp=='\n' && (m_Flags&regNewLine)) || (sp<m_mEnd && !isWordableChar(*sp))) && (sp>m_mBegin && isWordableChar(*(sp-1)))))
+ return NULL;
+ break;
+ case CSop::opQuest1:
+ break;
+ case CSop::opOr0: // Matches null, but needs to skip
+ ss++;
+ s = m_Strip[ss];
+ do{
+ ASSERT(s.m_Operator==CSop::opOr1);
+ ss+=s.m_Operand;
+ }while((s=m_Strip[ss]).m_Operator!=CSop::opChoice1);
+ // Now we should note that ss++ gets us past the Choice1..
+ break;
+ default:
+ // Have to make a choice..
+ hard=TRUE;
+ break;
+ }
+ }
+ if(!hard){ // That was it..
+ if(sp!=end)
+ return NULL;
+ return sp;
+ }
+ ss--; // Adjust for ther for's final increment..
+ // Hard stuff.. is going on and on..
+CSop s = m_Strip[ss];
+int i, len, offsave;
+int ssub,esub;
+LPCTSTR ssp, dp;
+ switch(s.m_Operator){
+ case CSop::opBackRef0: // The vilest depths they say.. If I only knew what the 'viles' stands for..
+ i = s.m_Operand;
+ ASSERT(0<i && i<=m_Subexps);
+ if(m_Matches[i].m_End<0)
+ return NULL;
+ ASSERT(m_Matches[i].m_Begin>=0);
+ len = m_Matches[i].GetLength();
+ ASSERT((end-m_mBegin)>=len);
+ if(sp>end-len)
+ return NULL; // Not enough left to match..
+ ssp = m_mBegin+m_Matches[i].m_Begin;
+ if(memcmp(sp,ssp,len))
+ return NULL;
+ while(m_Strip[ss]!=CSop(CSop::opBackRef1,i))
+ ss++;
+ return MatchBackRef(sp+len,end,ss+1,to,level-1);
+ break;
+ case CSop::opQuest0: // to null or not they wonder..
+ dp = MatchBackRef(sp,end,ss+1,to,level);
+ if(dp)
+ return dp; // not..
+ return MatchBackRef(sp,end,ss+s.m_Operand+1,to,level-1);
+ break;
+ case CSop::opPlus0:
+ ASSERT(m_mLastPos.GetSize());
+ ASSERT(level+1 <= m_Pluses);
+ m_mLastPos[level+1]=sp;
+ return MatchBackRef(sp,end,ss+1,to,level+1);
+ break;
+ case CSop::opPlus1:
+ if(sp == m_mLastPos[level]) // Last pass matched null
+ return MatchBackRef(sp,end,ss+1,to,level-1);
+ // Try another pass..
+ m_mLastPos[level]=sp;
+ dp = MatchBackRef(sp,end,ss-s.m_Operand+1,to,level);
+ if(dp)
+ return dp;
+ return MatchBackRef(sp,end,ss+1,to,level-1);
+ break;
+ case CSop::opChoice0: // find the right one, ifany
+ ssub = ss+1;
+ esub = ss+s.m_Operand-1;
+ ASSERT(m_Strip[esub].m_Operator==CSop::opOr0);
+ for(;;){ // Find first matching branch.
+ dp = MatchBackRef(sp,end,ssub,esub,level);
+ if(dp)
+ return dp;
+ // This one missed, try next one..
+ if(m_Strip[esub].m_Operator==CSop::opChoice1)
+ return NULL; // There is none..
+ esub++;
+ ASSERT(m_Strip[esub].m_Operator==CSop::opOr1);
+ ssub=esub+1;
+ esub+=m_Strip[esub].m_Operand;
+ if(m_Strip[esub].m_Operator==CSop::opOr1)
+ esub--;
+ else
+ ASSERT(m_Strip[esub].m_Operator==CSop::opChoice1);
+ }
+ break;
+ case CSop::opLeftParen: // Must undo assignment if rest fails..
+ i = s.m_Operand;
+ ASSERT(0<i && i<=m_Subexps);
+ offsave = m_Matches[i].m_Begin;
+ m_Matches[i].m_Begin = sp-m_mBegin;
+ dp = MatchBackRef(sp,end,ss+1,to,level);
+ if(dp)
+ return dp;
+ m_Matches[i].m_Begin=offsave;
+ return NULL;
+ break;
+ case CSop::opRightParen: // Must undo assignment if rest fails..
+ i = s.m_Operand;
+ ASSERT(0<i && i<=m_Subexps);
+ offsave = m_Matches[i].m_End;
+ m_Matches[i].m_End = sp-m_mBegin;
+ dp = MatchBackRef(sp,end,ss+1,to,level);
+ if(dp)
+ return dp;
+ m_Matches[i].m_End = offsave;
+ return NULL;
+ break;
+#ifdef _DEBUG
+ default:
+ ASSERT(FALSE);
+ break;
+#endif
+ }
+ ASSERT(FALSE);
+ return NULL; // Anyway - we can never get here..
+}
+
+#ifdef _DEBUG
+void CRegEx::CSop::Dump(CDumpContext& dc)
+{
+ switch(m_Operator){
+ case opEnd:
+ dc << "end";
+ break;
+ case opChar:
+ dc << "char('" << (char)m_Operand << "')";
+ break;
+ case opBOL:
+ dc << "BOL";
+ break;
+ case opEOL:
+ dc << "EOL";
+ break;
+ case opAny:
+ dc << "any";
+ break;
+ case opAnyOf:
+ dc << "anyOf(" << m_Operand << ")";
+ break;
+ case opBackRef0:
+ dc << "[ backref(" << m_Operand << ")";
+ break;
+ case opBackRef1:
+ dc << "] backref(" << m_Operand << ")";
+ break;
+ case opPlus0:
+ dc << "[ + (" << m_Operand << ")";
+ break;
+ case opPlus1:
+ dc << "] + (" << m_Operand << ")";
+ break;
+ case opQuest0:
+ dc << "[ ? (" << m_Operand << ")";
+ break;
+ case opQuest1:
+ dc << "] ? (" << m_Operand << ")";
+ break;
+ case opLeftParen:
+ dc << "[ ( (" << m_Operand << ")";
+ break;
+ case opRightParen:
+ dc << "] ) (" << m_Operand << ")";
+ break;
+ case opChoice0:
+ dc << "[ choice (" << m_Operand << ")";
+ break;
+ case opOr0:
+ dc << "[ | (" << m_Operand << ")";
+ break;
+ case opOr1:
+ dc << "] | (" << m_Operand << ")";
+ break;
+ case opChoice1:
+ dc << "] choice (" << m_Operand << ")";
+ break;
+ case opBOW:
+ dc << "BOW";
+ break;
+ case opEOW:
+ dc << "EOW";
+ break;
+ }
+}
+void CRegEx::DumpStrip(CDumpContext& dc)
+{
+ for(int tmp=0;tmp<m_Strip.GetSize();tmp++)
+ dc << tmp << ": " << m_Strip[tmp] << ";\n";
+}
+#endif
+
+
+CString CRegEx::GetMatch(int match)
+{
+CString rv;
+ if(!m_Matches.GetSize())
+ return rv;
+ ASSERT(m_Matches[0].m_Begin<m_Input.GetLength() && m_Matches[0].m_End<=m_Input.GetLength());
+ if(match==matchPreMatch)
+ return m_Input.Left(m_Matches[0].m_Begin);
+ if(match==matchPostMatch)
+ return m_Input.Mid(m_Matches[0].m_End);
+ if(match<0 || match >= m_Matches.GetSize())
+ return rv;
+ if(m_Matches[match].m_Begin<0 || m_Matches[match].m_End<0)
+ return rv;
+ ASSERT(m_Matches[match].m_Begin<m_Input.GetLength() && m_Matches[match].m_End<=m_Input.GetLength());
+ rv = m_Input.Mid(m_Matches[match].m_Begin,m_Matches[match].m_End-m_Matches[match].m_Begin);
+ return rv;
+}
diff --git a/shared-code/RegEx.h b/shared-code/RegEx.h
new file mode 100644
index 0000000..2534768
--- a/dev/null
+++ b/shared-code/RegEx.h
@@ -0,0 +1,158 @@
+#ifndef __REGEX_H
+#define __REGEX_H
+
+class CRegEx {
+public:
+ CString GetMatch(int match=0);
+ CString m_Input;
+ struct CMatch {
+ CMatch() : m_Begin(-1), m_End(-1) {}
+ int GetLength() { return m_End-m_Begin; }
+ int m_Begin;
+ int m_End;
+ };
+ typedef CArray<CMatch,CMatch&> CMatchBox;
+ enum {
+ matchMatch = 0,
+ matchPreMatch = -1,
+ matchPostMatch = -2
+ };
+ CMatchBox m_Matches;
+ enum {
+ charOut = 256,
+ charBOL, charEOL, charBOLEOL, charNothing, charBOW, charEOW,
+ charMaxCode = charEOW,
+ charNNChars = (charMaxCode-255)
+ };
+ int m_mFlags;
+ enum {
+ regeSuccess = 0,
+ regeNoMatch = 1, regeBadPattern, regeCollate, regeCType, regeEscape, regeSubReg, regeBracket,
+ regeParen, regeBrace, regeBadBrace, regeRange, regeSpace, regeBadRepeat, regeEmpty, regeAssert,
+ regeInvArg
+ };
+ int m_Error;
+ CRegEx();
+ BOOL m_bCompiled;
+ CString m_Pattern;
+ BOOL m_bBackRefs;
+ int m_Pluses;
+ CString m_Must;
+ BYTE m_Category[CHAR_MAX-CHAR_MIN+1];
+ int m_Categories;
+ int m_EOLs;
+ int m_BOLs;
+ int m_iFlags;
+ int m_Subexps;
+ struct CSop {
+ void Dump(CDumpContext& dc);
+ CSop() {}
+ CSop(BYTE op,DWORD opnd=0) : m_Operator(op), m_Operand(opnd) {}
+ BOOL operator==(CSop& other) {return m_Operator==other.m_Operator && m_Operand==other.m_Operand;}
+ BOOL operator!=(CSop& other) { return !((*this)==other);}
+ enum {
+ opEnd = 1, opChar, opBOL, opEOL, opAny, opAnyOf, opBackRef0, opBackRef1,
+ opPlus0, opPlus1, opQuest0, opQuest1, opLeftParen, opRightParen, opChoice0,
+ opOr0, opOr1, opChoice1, opBOW, opEOW
+ };
+ BYTE m_Operator;
+ DWORD m_Operand;
+ enum {
+ stCurrent = 1, stFresh = 2, stTemp = 4, stEmpty = 8
+ };
+ BYTE m_MatchData;
+ };
+ typedef CArray<CSop,CSop&> CStrip;
+ CStrip m_Strip;
+ int m_Flags;
+ struct CSet {
+ CSet() : m_Hash(0) { memset(m_Set,0,sizeof(m_Set)); }
+ CSet(CSet& src) { (*this)=src; }
+ CSet& operator=(CSet& src) { memmove(this,&src,sizeof(*this)); return *this; }
+ BOOL operator==(CSet& other) { if(m_Hash!=other.m_Hash)return FALSE;return !memcmp(m_Set,other.m_Set,sizeof(m_Set)); }
+ enum {
+ size = (CHAR_MAX-CHAR_MIN+1)
+ };
+ BOOL m_Set[size];
+ BYTE m_Hash;
+ public:
+ UCHAR GetOnly();
+ void Sub(UCHAR c);
+ BOOL IsIn(UCHAR c);
+ void Add(UCHAR c);
+ };
+ typedef CArray<CSet,CSet&> CSets;
+ CSets m_Sets;
+ enum {
+ // Compile flags
+ regBasic = 0, regExtended = 1,
+ regIgnoreCase = 2,
+ regNoSubExpressions = 4, // Also works for matching.
+ regNewLine = 16,
+ regLiteral = 32,
+ // Match Flags
+ regNotBOL = 1,
+ regNotEOL = 2,
+ regOneMatch=64,
+ regBackRefs=128,
+ // iFlags
+ iflagsUseBOL=1, iflagsUseEOL=2, iflagsBad=4
+ };
+ CString Replace(LPCTSTR src,LPCTSTR rep,int flags=0);
+ BOOL Match(LPCTSTR src,int flags=0);
+ BOOL Compile(LPCTSTR regex,int flags=0);
+private:
+#ifdef _DEBUG
+ void DumpStrip(CDumpContext& dc);
+#endif
+ LPCTSTR MatchBackRef(LPCTSTR begin,LPCTSTR end,int from,int to,int level);
+ typedef CArray<LPCTSTR,LPCTSTR> CStrPtrArray;
+ CStrPtrArray m_mLastPos;
+ LPCTSTR MatchDissect(LPCTSTR begin,LPCTSTR end,int from,int to);
+ LPCTSTR MatchSlow(LPCTSTR begin,LPCTSTR end,int from,int to);
+ LPCTSTR m_cOldP;
+ BOOL MatchStatesEqual(BYTE m1,BYTE m2);
+ LPCTSTR m_mBegin;
+ void MatchStatesCopy(BYTE dst,BYTE src);
+ void MatchStep(int from,int to,BYTE maskBefore,int charCode,BYTE maskAfter);
+ void MatchStatesClear(BYTE mask);
+ LPCTSTR MatchFast(LPCTSTR begin);
+ LPCTSTR m_mEnd;
+ LPCTSTR m_mPointer;
+ BOOL ParseBREexp(BOOL ordinaryStar);
+ void ParseBRE(int stopa=0,int stopb=0);
+ void ParseLiteral();
+ int CountPluses();
+ void FigureMust();
+ BOOL IsInSameSets(UCHAR c1,UCHAR c2);
+ BOOL IsInSets(UCHAR c);
+ void Categorize();
+ int StripDuplicate(int from,int to);
+ void EmitRepeat(int pos,int from,int to);
+ UCHAR ParseBracketSymbol();
+ UCHAR ParseBracketCollatingElement(UCHAR term);
+ void ParseBracketEClass(CSet& cset);
+ void ParseBracketCClass(CSet& cset);
+ void ParseBracketTerm(CSet& cset);
+ int StoreSet(CSet& cset);
+ void ParseBracket();
+ int ParseCount();
+ void EmitNonNewLineAny();
+ void EmitOrdinary(UCHAR c);
+ void StripInsert(int pos,CSop& sop);
+ void ParseEREexp();
+ void ParseERE(int stop=0);
+ struct CParenthesis {
+ long m_Begin;
+ long m_End;
+ CParenthesis(long b=0,long e=0) : m_Begin(b), m_End(e) {}
+ };
+ typedef CArray<CParenthesis,CParenthesis&> CParens;
+ CParens m_ParseParens;
+ int m_ParsePointer;
+};
+#ifdef _DEBUG
+inline CDumpContext& operator<<(CDumpContext& dc, CRegEx::CSop& sop) { sop.Dump(dc); return dc; }
+#endif
+
+#endif // __REGEX_H \ No newline at end of file
diff --git a/shared-code/SNMPExtDll.h b/shared-code/SNMPExtDll.h
new file mode 100644
index 0000000..14c920d
--- a/dev/null
+++ b/shared-code/SNMPExtDll.h
@@ -0,0 +1,252 @@
+#ifndef __SNMPEXTDLL_H
+#define __SNMPEXTDLL_H
+
+#include "snmpeer.h"
+
+#include <snmp.h>
+
+namespace Klever {
+
+class CSNMPExtDLL : public CSNMPeer {
+public:
+ HINSTANCE m_hInstance;
+ HANDLE m_hEvent;
+ AsnObjectIdentifier m_OID;
+ BOOL (SNMP_FUNC_TYPE *m_extInit)(DWORD dw,HANDLE h,AsnObjectIdentifier* aoid);
+ BOOL (SNMP_FUNC_TYPE *m_extQuery)(BYTE b,RFC1157VarBindList* rvbl,AsnInteger* ai1,AsnInteger* ai2);
+ BOOL (SNMP_FUNC_TYPE *m_extTrap)(AsnObjectIdentifier*,AsnNetworkAddress*,AsnInteger*,AsnInteger*,AsnTimeticks*,RFC1157VarBindList*);
+
+ HINSTANCE m_hSNMPAPI;
+ void (SNMP_FUNC_TYPE *m_snmpOIDFree)(AsnObjectIdentifier*);
+ LPVOID (SNMP_FUNC_TYPE *m_snmpAlloc)(UINT);
+ void (SNMP_FUNC_TYPE *m_snmpFree)(LPVOID);
+ void (SNMP_FUNC_TYPE *m_snmpVBLFree)(RFC1157VarBindList* vbl);
+ void InitSNMP() {
+ m_hSNMPAPI = ::LoadLibraryEx("SNMPAPI",NULL,0);
+ if(!m_hSNMPAPI)
+ return;
+ *(FARPROC*)&m_snmpOIDFree = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilOidFree");
+ *(FARPROC*)&m_snmpAlloc = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilMemAlloc");
+ *(FARPROC*)&m_snmpFree = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilMemFree");
+ *(FARPROC*)&m_snmpVBLFree = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilVarBindListFree");
+ if(
+ (m_snmpFree && !m_snmpAlloc) ||
+ (m_snmpAlloc && !m_snmpFree)
+ )
+ DeinitSNMP();
+ }
+ void DeinitSNMP() {
+ if(!m_hSNMPAPI)
+ return;
+ ::FreeLibrary(m_hSNMPAPI);
+ m_hSNMPAPI=NULL;
+ }
+ void SNMPFreeOID(AsnObjectIdentifier* oid) {
+ if(m_hSNMPAPI && m_snmpOIDFree)
+ (*m_snmpOIDFree)(oid);
+ else
+ ::GlobalFree((HGLOBAL)oid->ids);
+ }
+ LPVOID SNMPAlloc(UINT size) {
+ if(m_hSNMPAPI && m_snmpAlloc)
+ return (*m_snmpAlloc)(size);
+ else
+ return ::GlobalAlloc(GMEM_FIXED,size);
+ }
+ void SNMPFree(LPVOID addr) {
+ if(m_hSNMPAPI && m_snmpFree)
+ (*m_snmpFree)(addr);
+ else
+ :: GlobalFree((HGLOBAL)addr);
+ }
+ void SNMPFreeVBL(RFC1157VarBindList& vbl) {
+ if(m_hSNMPAPI && m_snmpVBLFree)
+ (*m_snmpVBLFree)(&vbl);
+ else{
+ for(UINT tmp=0;tmp<vbl.len;tmp++) {
+ SNMPFree(vbl.list[tmp].name.ids);
+ switch(vbl.list[tmp].value.asnType){
+ case ASN_OCTETSTRING:
+ case ASN_SEQUENCE:
+ case ASN_RFC1155_IPADDRESS:
+ case ASN_RFC1155_OPAQUE:
+// case ASN_RFC1213_DISPSTRING:
+ if(vbl.list[tmp].value.asnValue.arbitrary.dynamic)
+ SNMPFree(vbl.list[tmp].value.asnValue.arbitrary.stream);
+ break;
+ case ASN_OBJECTIDENTIFIER:
+ SNMPFree(vbl.list[tmp].value.asnValue.object.ids);
+ break;
+ default:
+ break;
+ }
+ }
+ SNMPFree(vbl.list);
+ }
+ }
+
+ BOOL SNMPBuildVBL(RFC1157VarBindList& vbl,CSNMPVarBindList& in) {
+ vbl.len = in.GetCount();
+ vbl.list = (RFC1157VarBind*)SNMPAlloc(sizeof(RFC1157VarBind)*vbl.len);
+ POSITION p = in.GetHeadPosition();
+ UINT ptr = 0;
+ while(p){
+ CSNMPVarBind& vb = in.GetNext(p);
+ ASSERT(ptr<vbl.len);
+ SNMPBuildVB(vbl.list[ptr++],vb);
+ }
+ return TRUE;
+ }
+ BOOL SNMPBuildVB(RFC1157VarBind& vb,CSNMPVarBind& in) {
+ ASSERT(in.name.type==CASNAny::typeASNOID);
+ return SNMPBuildOID(vb.name,in.name.value.oid) && SNMPBuildAA(vb.value,in.value);
+ }
+ BOOL SNMPBuildAA(AsnAny& aa,CASNAny& in) {
+ aa.asnType=in.type;
+ switch(in.type) {
+ case CASNAny::typeASNInteger:
+ aa.asnValue.number=in.value.number; break;
+ case CASNAny::typeASNOctetString:
+// case CASNAny::typeASNDispString:
+ SNMPBuildOS(aa.asnValue.string,in.value.string); break;
+ case CASNAny::typeASNNull:
+ break;
+ case CASNAny::typeASNOID:
+ SNMPBuildOID(aa.asnValue.object,in.value.oid); break;
+ case CASNAny::typeASNSequence:
+// case CASNAny::typeASNSequenceOf:
+ SNMPBuildOS(aa.asnValue.sequence,in.value.sequence); break;
+ case CASNAny::typeASNIP:
+ SNMPBuildFLOS(aa.asnValue.address,(LPBYTE)&in.value.ip,sizeof(in.value.ip)); break;
+ case CASNAny::typeASNCounter:
+ aa.asnValue.counter = in.value.counter; break;
+ case CASNAny::typeASNGauge:
+ aa.asnValue.gauge = in.value.gauge; break;
+ case CASNAny::typeASNTicks:
+ aa.asnValue.ticks = in.value.ticks; break;
+ case CASNAny::typeASNOpaque:
+ ASSERT(in.storeType==CASNAny::storeDynamic);
+ SNMPBuildOS(aa.asnValue.arbitrary,in.value.data); break;
+ break;
+ default:
+ ASSERT(FALSE);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ BOOL SNMPBuildOS(AsnOctetString& os,CASNAny::asnOctetString& in) {
+ return SNMPBuildFLOS(os,in.data,in.size);
+ }
+ BOOL SNMPBuildOID(AsnObjectIdentifier& oid,CASNAny::asnOID& in) {
+ oid.idLength = in.size/sizeof(UINT);
+ ASSERT(!(in.size%sizeof(UINT)));
+ VERIFY(oid.ids = (UINT*)SNMPAlloc(in.size));
+ memmove(oid.ids,in.data,in.size);
+ return TRUE;
+ }
+ BOOL SNMPBuildFLOS(AsnOctetString& os,LPBYTE data,UINT size) {
+ os.length = size;
+ VERIFY(os.stream = (BYTE*)SNMPAlloc(os.length));
+ os.dynamic=TRUE;
+ memmove(os.stream,data,size);
+ return TRUE;
+ }
+ BOOL SNMPParseVBL(RFC1157VarBindList& vbl,CSNMPVarBindList& ou) {
+ for(UINT tmp=0;tmp<vbl.len;tmp++){
+ CSNMPVarBind vb;
+ SNMPParseVB(vbl.list[tmp],vb);
+ ou.AddTail(vb);
+ }
+ return TRUE;
+ }
+ BOOL SNMPParseVB(RFC1157VarBind& vb,CSNMPVarBind& ou) {
+ ou.name.Set(CASNAny::typeASNOID,(LPBYTE)vb.name.ids,vb.name.idLength*sizeof(UINT));
+ return SNMPParseAA(vb.value,ou.value);
+ }
+ BOOL SNMPParseAA(AsnAny& aa,CASNAny& ou) {
+ switch(aa.asnType){
+ case ASN_INTEGER:
+ ou.Set(CASNAny::typeASNInteger,aa.asnValue.number); break;
+ case ASN_OCTETSTRING:
+// case ASN_RFC1213_DISPSTRING:
+ ou.Set(CASNAny::typeASNOctetString,aa.asnValue.string.stream,aa.asnValue.string.length); break;
+ case ASN_OBJECTIDENTIFIER:
+ ou.Set(CASNAny::typeASNOID,(LPBYTE)aa.asnValue.object.ids,aa.asnValue.object.idLength);
+ SNMPParseOID(aa.asnValue.object,ou.value.oid); break;
+ case ASN_SEQUENCE:
+ ou.Set(CASNAny::typeASNSequence,aa.asnValue.sequence.stream,aa.asnValue.sequence.length); break;
+ case ASN_RFC1155_IPADDRESS:
+ SNMPParseIP(aa.asnValue.address,ou); break;
+ case ASN_RFC1155_COUNTER:
+ ou.Set(CASNAny::typeASNCounter,(LONG)aa.asnValue.counter); break;
+ case ASN_RFC1155_GAUGE:
+ ou.Set(CASNAny::typeASNGauge,(LONG)aa.asnValue.gauge); break;
+ case ASN_RFC1155_TIMETICKS:
+ ou.Set(CASNAny::typeASNTicks,(LONG)aa.asnValue.ticks); break;
+ case ASN_RFC1155_OPAQUE:
+ ou.Set(CASNAny::typeASNOpaque,aa.asnValue.arbitrary.stream,aa.asnValue.arbitrary.length); break;
+ case ASN_NULL:
+ ou.Free(); break;
+ default:
+ ASSERT(FALSE);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ BOOL SNMPParseOID(AsnObjectIdentifier& oid,CASNAny::asnOID& ou) {
+ ASSERT(ou.size==(oid.idLength*sizeof(UINT)));
+ memmove(ou.data,oid.ids,ou.size);
+ return TRUE;
+ }
+ BOOL SNMPParseIP(AsnIPAddress& ip,CASNAny& ou) {
+ in_addr i;
+ if(ip.length>sizeof(i))
+ return FALSE;
+ i.s_addr=0;
+ memmove(&i,ip.stream,ip.length);
+ ou.Set(i);
+ return TRUE;
+ }
+
+
+ CSNMPExtDLL(LPCTSTR dllName) : m_hInstance(NULL) { InitSNMP(); Init(dllName); }
+ ~CSNMPExtDLL() { Deinit(); DeinitSNMP(); }
+
+ BOOL Init(LPCTSTR dllName) {
+ Deinit();
+ m_hInstance = ::LoadLibraryEx(dllName,NULL,0);
+ if(!m_hInstance)
+ return FALSE;
+ *(FARPROC*)&m_extInit = ::GetProcAddress(m_hInstance,"SnmpExtensionInit");
+ *(FARPROC*)&m_extQuery = ::GetProcAddress(m_hInstance,"SnmpExtensionQuery");
+ *(FARPROC*)&m_extTrap = ::GetProcAddress(m_hInstance,"SnmpExtensionTrap");
+ if(!(m_extInit && m_extQuery && m_extTrap)){
+ Deinit();
+ return FALSE;
+ }
+ if(!((*m_extInit)(GetCurrentTime(),&m_hEvent,&m_OID))){
+ Deinit();
+ return FALSE;
+ }
+ return TRUE;
+ }
+ void Deinit() {
+ if(!m_hInstance)
+ return;
+ ::FreeLibrary(m_hInstance);
+ }
+ virtual BOOL Request(BYTE type,CSNMPVarBindList& in,CSNMPVarBindList& ou) {
+ RFC1157VarBindList vbl;
+ SNMPBuildVBL(vbl,in);
+ AsnInteger errorStatus, errorIndex;
+ (*m_extQuery)(type,&vbl,&errorStatus,&errorIndex);
+ ou.RemoveAll();
+ SNMPParseVBL(vbl,ou);
+ SNMPFreeVBL(vbl);
+ return TRUE;
+ }
+};
+
+};
+
+#endif // __SNMPEXTDLL_H
diff --git a/shared-code/SNMPOIDs.h b/shared-code/SNMPOIDs.h
new file mode 100644
index 0000000..68ee659
--- a/dev/null
+++ b/shared-code/SNMPOIDs.h
@@ -0,0 +1,221 @@
+#ifndef __SNMPOIDS_H
+#define __SNMPOIDS_H
+
+#define DEFINE_OID(name,oid) static UINT name[] = oid
+
+// MIB-II OIDs
+
+#define OIDccitt {0}
+#define OIDnull {0,0}
+#define OIDiso {1}
+#define OIDorg {1,3}
+#define OIDdod {1,3,6}
+#define OIDinternet {1,3,6,1}
+#define OIDdirectory {1,3,6,1,1}
+#define OIDmgmt {1,3,6,1,2}
+#define OIDmib_2 {1,3,6,1,2,1}
+#define OIDsystem {1,3,6,1,2,1,1}
+#define OIDsysDescr {1,3,6,1,2,1,1,1}
+#define OIDsysObjectID {1,3,6,1,2,1,1,2}
+#define OIDsysUpTime {1,3,6,1,2,1,1,3}
+#define OIDsysContact {1,3,6,1,2,1,1,4}
+#define OIDsysName {1,3,6,1,2,1,1,5}
+#define OIDsysLocation {1,3,6,1,2,1,1,6}
+#define OIDsysServices {1,3,6,1,2,1,1,7}
+#define OIDtransmission {1,3,6,1,2,1,10}
+#define OIDsnmp {1,3,6,1,2,1,11}
+#define OIDsnmpInPkts {1,3,6,1,2,1,11,1}
+#define OIDsnmpInBadValues {1,3,6,1,2,1,11,10}
+#define OIDsnmpInReadOnlys {1,3,6,1,2,1,11,11}
+#define OIDsnmpInGenErrs {1,3,6,1,2,1,11,12}
+#define OIDsnmpInTotalReqVars {1,3,6,1,2,1,11,13}
+#define OIDsnmpInTotalSetVars {1,3,6,1,2,1,11,14}
+#define OIDsnmpInGetRequests {1,3,6,1,2,1,11,15}
+#define OIDsnmpInGetNexts {1,3,6,1,2,1,11,16}
+#define OIDsnmpInSetRequests {1,3,6,1,2,1,11,17}
+#define OIDsnmpInGetResponses {1,3,6,1,2,1,11,18}
+#define OIDsnmpInTraps {1,3,6,1,2,1,11,19}
+#define OIDsnmpOutPkts {1,3,6,1,2,1,11,2}
+#define OIDsnmpOutTooBigs {1,3,6,1,2,1,11,20}
+#define OIDsnmpOutNoSuchNames {1,3,6,1,2,1,11,21}
+#define OIDsnmpOutBadValues {1,3,6,1,2,1,11,22}
+#define OIDsnmpOutGenErrs {1,3,6,1,2,1,11,24}
+#define OIDsnmpOutGetRequests {1,3,6,1,2,1,11,25}
+#define OIDsnmpOutGetNexts {1,3,6,1,2,1,11,26}
+#define OIDsnmpOutSetRequests {1,3,6,1,2,1,11,27}
+#define OIDsnmpOutGetResponses {1,3,6,1,2,1,11,28}
+#define OIDsnmpOutTraps {1,3,6,1,2,1,11,29}
+#define OIDsnmpInBadVersions {1,3,6,1,2,1,11,3}
+#define OIDsnmpEnableAuthenTraps {1,3,6,1,2,1,11,30}
+#define OIDsnmpInBadCommunityNames {1,3,6,1,2,1,11,4}
+#define OIDsnmpInBadCommunityUses {1,3,6,1,2,1,11,5}
+#define OIDsnmpInASNParseErrs {1,3,6,1,2,1,11,6}
+#define OIDsnmpInTooBigs {1,3,6,1,2,1,11,8}
+#define OIDsnmpInNoSuchNames {1,3,6,1,2,1,11,9}
+#define OIDinterfaces {1,3,6,1,2,1,2}
+#define OIDifNumber {1,3,6,1,2,1,2,1}
+#define OIDifTable {1,3,6,1,2,1,2,2}
+#define OIDifEntry {1,3,6,1,2,1,2,2,1}
+#define OIDifIndex {1,3,6,1,2,1,2,2,1,1}
+#define OIDifInOctets {1,3,6,1,2,1,2,2,1,10}
+#define OIDifInUcastPkts {1,3,6,1,2,1,2,2,1,11}
+#define OIDifInNUcastPkts {1,3,6,1,2,1,2,2,1,12}
+#define OIDifInDiscards {1,3,6,1,2,1,2,2,1,13}
+#define OIDifInErrors {1,3,6,1,2,1,2,2,1,14}
+#define OIDifInUnknownProtos {1,3,6,1,2,1,2,2,1,15}
+#define OIDifOutOctets {1,3,6,1,2,1,2,2,1,16}
+#define OIDifOutUcastPkts {1,3,6,1,2,1,2,2,1,17}
+#define OIDifOutNUcastPkts {1,3,6,1,2,1,2,2,1,18}
+#define OIDifOutDiscards {1,3,6,1,2,1,2,2,1,19}
+#define OIDifDescr {1,3,6,1,2,1,2,2,1,2}
+#define OIDifOutErrors {1,3,6,1,2,1,2,2,1,20}
+#define OIDifOutQLen {1,3,6,1,2,1,2,2,1,21}
+#define OIDifSpecific {1,3,6,1,2,1,2,2,1,22}
+#define OIDifType {1,3,6,1,2,1,2,2,1,3}
+#define OIDifMtu {1,3,6,1,2,1,2,2,1,4}
+#define OIDifSpeed {1,3,6,1,2,1,2,2,1,5}
+#define OIDifPhysAddress {1,3,6,1,2,1,2,2,1,6}
+#define OIDifAdminStatus {1,3,6,1,2,1,2,2,1,7}
+#define OIDifOperStatus {1,3,6,1,2,1,2,2,1,8}
+#define OIDifLastChange {1,3,6,1,2,1,2,2,1,9}
+#define OIDat {1,3,6,1,2,1,3}
+#define OIDatTable {1,3,6,1,2,1,3,1}
+#define OIDatEntry {1,3,6,1,2,1,3,1,1}
+#define OIDatIfIndex {1,3,6,1,2,1,3,1,1,1}
+#define OIDatPhysAddress {1,3,6,1,2,1,3,1,1,2}
+#define OIDatNetAddress {1,3,6,1,2,1,3,1,1,3}
+#define OIDip {1,3,6,1,2,1,4}
+#define OIDipForwarding {1,3,6,1,2,1,4,1}
+#define OIDipOutRequests {1,3,6,1,2,1,4,10}
+#define OIDipOutDiscards {1,3,6,1,2,1,4,11}
+#define OIDipOutNoRoutes {1,3,6,1,2,1,4,12}
+#define OIDipReasmTimeout {1,3,6,1,2,1,4,13}
+#define OIDipReasmReqds {1,3,6,1,2,1,4,14}
+#define OIDipReasmOKs {1,3,6,1,2,1,4,15}
+#define OIDipReasmFails {1,3,6,1,2,1,4,16}
+#define OIDipFragOKs {1,3,6,1,2,1,4,17}
+#define OIDipFragFails {1,3,6,1,2,1,4,18}
+#define OIDipFragCreates {1,3,6,1,2,1,4,19}
+#define OIDipDefaultTTL {1,3,6,1,2,1,4,2}
+#define OIDipAddrTable {1,3,6,1,2,1,4,20}
+#define OIDipAddrEntry {1,3,6,1,2,1,4,20,1}
+#define OIDipAdEntAddr {1,3,6,1,2,1,4,20,1,1}
+#define OIDipAdEntIfIndex {1,3,6,1,2,1,4,20,1,2}
+#define OIDipAdEntNetMask {1,3,6,1,2,1,4,20,1,3}
+#define OIDipAdEntBcastAddr {1,3,6,1,2,1,4,20,1,4}
+#define OIDipAdEntReasmMaxSize {1,3,6,1,2,1,4,20,1,5}
+#define OIDipRouteTable {1,3,6,1,2,1,4,21}
+#define OIDipRouteEntry {1,3,6,1,2,1,4,21,1}
+#define OIDipRouteDest {1,3,6,1,2,1,4,21,1,1}
+#define OIDipRouteAge {1,3,6,1,2,1,4,21,1,10}
+#define OIDipRouteMask {1,3,6,1,2,1,4,21,1,11}
+#define OIDipRouteMetric5 {1,3,6,1,2,1,4,21,1,12}
+#define OIDipRouteInfo {1,3,6,1,2,1,4,21,1,13}
+#define OIDipRouteIfIndex {1,3,6,1,2,1,4,21,1,2}
+#define OIDipRouteMetric1 {1,3,6,1,2,1,4,21,1,3}
+#define OIDipRouteMetric2 {1,3,6,1,2,1,4,21,1,4}
+#define OIDipRouteMetric3 {1,3,6,1,2,1,4,21,1,5}
+#define OIDipRouteMetric4 {1,3,6,1,2,1,4,21,1,6}
+#define OIDipRouteNextHop {1,3,6,1,2,1,4,21,1,7}
+#define OIDipRouteType {1,3,6,1,2,1,4,21,1,8}
+#define OIDipRouteProto {1,3,6,1,2,1,4,21,1,9}
+#define OIDipNetToMediaTable {1,3,6,1,2,1,4,22}
+#define OIDipNetToMediaEntry {1,3,6,1,2,1,4,22,1}
+#define OIDipNetToMediaIfIndex {1,3,6,1,2,1,4,22,1,1}
+#define OIDipNetToMediaPhysAddress {1,3,6,1,2,1,4,22,1,2}
+#define OIDipNetToMediaNetAddress {1,3,6,1,2,1,4,22,1,3}
+#define OIDipNetToMediaType {1,3,6,1,2,1,4,22,1,4}
+#define OIDipRoutingDiscards {1,3,6,1,2,1,4,23}
+#define OIDipInReceives {1,3,6,1,2,1,4,3}
+#define OIDipInHdrErrors {1,3,6,1,2,1,4,4}
+#define OIDipInAddrErrors {1,3,6,1,2,1,4,5}
+#define OIDipForwDatagrams {1,3,6,1,2,1,4,6}
+#define OIDipInUnknownProtos {1,3,6,1,2,1,4,7}
+#define OIDipInDiscards {1,3,6,1,2,1,4,8}
+#define OIDipInDelivers {1,3,6,1,2,1,4,9}
+#define OIDicmp {1,3,6,1,2,1,5}
+#define OIDicmpInMsgs {1,3,6,1,2,1,5,1}
+#define OIDicmpInTimestamps {1,3,6,1,2,1,5,10}
+#define OIDicmpInTimestampReps {1,3,6,1,2,1,5,11}
+#define OIDicmpInAddrMasks {1,3,6,1,2,1,5,12}
+#define OIDicmpInAddrMaskReps {1,3,6,1,2,1,5,13}
+#define OIDicmpOutMsgs {1,3,6,1,2,1,5,14}
+#define OIDicmpOutErrors {1,3,6,1,2,1,5,15}
+#define OIDicmpOutDestUnreachs {1,3,6,1,2,1,5,16}
+#define OIDicmpOutTimeExcds {1,3,6,1,2,1,5,17}
+#define OIDicmpOutParmProbs {1,3,6,1,2,1,5,18}
+#define OIDicmpOutSrcQuenchs {1,3,6,1,2,1,5,19}
+#define OIDicmpInErrors {1,3,6,1,2,1,5,2}
+#define OIDicmpOutRedirects {1,3,6,1,2,1,5,20}
+#define OIDicmpOutEchos {1,3,6,1,2,1,5,21}
+#define OIDicmpOutEchoReps {1,3,6,1,2,1,5,22}
+#define OIDicmpOutTimestamps {1,3,6,1,2,1,5,23}
+#define OIDicmpOutTimestampReps {1,3,6,1,2,1,5,24}
+#define OIDicmpOutAddrMasks {1,3,6,1,2,1,5,25}
+#define OIDicmpOutAddrMaskReps {1,3,6,1,2,1,5,26}
+#define OIDicmpInDestUnreachs {1,3,6,1,2,1,5,3}
+#define OIDicmpInTimeExcds {1,3,6,1,2,1,5,4}
+#define OIDicmpInParmProbs {1,3,6,1,2,1,5,5}
+#define OIDicmpInSrcQuenchs {1,3,6,1,2,1,5,6}
+#define OIDicmpInRedirects {1,3,6,1,2,1,5,7}
+#define OIDicmpInEchos {1,3,6,1,2,1,5,8}
+#define OIDicmpInEchoReps {1,3,6,1,2,1,5,9}
+#define OIDtcp {1,3,6,1,2,1,6}
+#define OIDtcpRtoAlgorithm {1,3,6,1,2,1,6,1}
+#define OIDtcpInSegs {1,3,6,1,2,1,6,10}
+#define OIDtcpOutSegs {1,3,6,1,2,1,6,11}
+#define OIDtcpRetransSegs {1,3,6,1,2,1,6,12}
+#define OIDtcpConnTable {1,3,6,1,2,1,6,13}
+#define OIDtcpConnEntry {1,3,6,1,2,1,6,13,1}
+#define OIDtcpConnState {1,3,6,1,2,1,6,13,1,1}
+#define OIDtcpConnLocalAddress {1,3,6,1,2,1,6,13,1,2}
+#define OIDtcpConnLocalPort {1,3,6,1,2,1,6,13,1,3}
+#define OIDtcpConnRemAddress {1,3,6,1,2,1,6,13,1,4}
+#define OIDtcpConnRemPort {1,3,6,1,2,1,6,13,1,5}
+#define OIDtcpInErrs {1,3,6,1,2,1,6,14}
+#define OIDtcpOutRsts {1,3,6,1,2,1,6,15}
+#define OIDtcpRtoMin {1,3,6,1,2,1,6,2}
+#define OIDtcpRtoMax {1,3,6,1,2,1,6,3}
+#define OIDtcpMaxConn {1,3,6,1,2,1,6,4}
+#define OIDtcpActiveOpens {1,3,6,1,2,1,6,5}
+#define OIDtcpPassiveOpens {1,3,6,1,2,1,6,6}
+#define OIDtcpAttemptFails {1,3,6,1,2,1,6,7}
+#define OIDtcpEstabResets {1,3,6,1,2,1,6,8}
+#define OIDtcpCurrEstab {1,3,6,1,2,1,6,9}
+#define OIDudp {1,3,6,1,2,1,7}
+#define OIDudpInDatagrams {1,3,6,1,2,1,7,1}
+#define OIDudpNoPorts {1,3,6,1,2,1,7,2}
+#define OIDudpInErrors {1,3,6,1,2,1,7,3}
+#define OIDudpOutDatagrams {1,3,6,1,2,1,7,4}
+#define OIDudpTable {1,3,6,1,2,1,7,5}
+#define OIDudpEntry {1,3,6,1,2,1,7,5,1}
+#define OIDudpLocalAddress {1,3,6,1,2,1,7,5,1,1}
+#define OIDudpLocalPort {1,3,6,1,2,1,7,5,1,2}
+#define OIDegp {1,3,6,1,2,1,8}
+#define OIDegpInMsgs {1,3,6,1,2,1,8,1}
+#define OIDegpInErrors {1,3,6,1,2,1,8,2}
+#define OIDegpOutMsgs {1,3,6,1,2,1,8,3}
+#define OIDegpOutErrors {1,3,6,1,2,1,8,4}
+#define OIDegpNeighTable {1,3,6,1,2,1,8,5}
+#define OIDegpNeighEntry {1,3,6,1,2,1,8,5,1}
+#define OIDegpNeighState {1,3,6,1,2,1,8,5,1,1}
+#define OIDegpNeighStateUps {1,3,6,1,2,1,8,5,1,10}
+#define OIDegpNeighStateDowns {1,3,6,1,2,1,8,5,1,11}
+#define OIDegpNeighIntervalHello {1,3,6,1,2,1,8,5,1,12}
+#define OIDegpNeighIntervalPoll {1,3,6,1,2,1,8,5,1,13}
+#define OIDegpNeighMode {1,3,6,1,2,1,8,5,1,14}
+#define OIDegpNeighEventTrigger {1,3,6,1,2,1,8,5,1,15}
+#define OIDegpNeighAddr {1,3,6,1,2,1,8,5,1,2}
+#define OIDegpNeighAs {1,3,6,1,2,1,8,5,1,3}
+#define OIDegpNeighInMsgs {1,3,6,1,2,1,8,5,1,4}
+#define OIDegpNeighInErrs {1,3,6,1,2,1,8,5,1,5}
+#define OIDegpNeighOutMsgs {1,3,6,1,2,1,8,5,1,6}
+#define OIDegpNeighOutErrs {1,3,6,1,2,1,8,5,1,7}
+#define OIDegpNeighInErrMsgs {1,3,6,1,2,1,8,5,1,8}
+#define OIDegpNeighOutErrMsgs {1,3,6,1,2,1,8,5,1,9}
+#define OIDegpAs {1,3,6,1,2,1,8,6}
+#define OIDexperimental {1,3,6,1,3}
+#define OIDprivate {1,3,6,1,4}
+#define OIDenterprises {1,3,6,1,4,1}
+
+#endif // __SNMPOIDS_H \ No newline at end of file
diff --git a/shared-code/SNMPeer.h b/shared-code/SNMPeer.h
new file mode 100644
index 0000000..68f2efe
--- a/dev/null
+++ b/shared-code/SNMPeer.h
@@ -0,0 +1,286 @@
+#ifndef __SNMPEER_H
+#define __SNMPEER_H
+
+namespace Klever {
+
+class CASNAny {
+public:
+ enum {
+ asnCls = 0xC0,
+ asnClsUniversal = 0x00,
+ asnClsApplication = 0x40,
+ asnClsContextSpecific = 0x80,
+ asnClsPrivate = 0xC0,
+ asnConstructed = 0x20,
+ asnPrimitive = 0x00,
+ asnTag = 0x1F,
+ // ASN.1 Primitive Tags
+ asnTagInteger = 0x02,
+ asnTagOctetString = 0x04,
+ asnTagNull = 0x05,
+ asnTagOID = 0x06,
+ // ASN.1 Constructed Tags
+ asnTagSequence = 0x10,
+ // RFC1155 Primitive Tags
+ asnTagIP = 0x00,
+ asnTagCounter = 0x01,
+ asnTagGauge = 0x02,
+ asnTagTicks = 0x03,
+ asnTagOpaque = 0x04,
+ // RFC1213 alias
+ asnTagDispString = 0x04, // (ASN.1 Octet string)
+ // RFC1157 Constructed Tags
+ asnTagGetRequest = 0x00,
+ asnTagGetNextRequest = 0x01,
+ asnTagGetResponse = 0x02,
+ asnTagSetRequest = 0x03,
+ asnTagTrap = 0x04
+ };
+ enum {
+ typeASNInteger = (asnClsUniversal|asnPrimitive|asnTagInteger),
+ typeASNOctetString = (asnClsUniversal|asnPrimitive|asnTagOctetString),
+ typeASNNull = (asnClsUniversal|asnPrimitive|asnTagNull),
+ typeASNOID = (asnClsUniversal|asnPrimitive|asnTagOID),
+
+ typeASNSequence = (asnClsUniversal|asnConstructed|asnTagSequence),
+ typeASNSequenceOf = (asnClsUniversal|asnConstructed|asnTagSequence),
+
+ typeASNIP = (asnClsApplication|asnPrimitive|asnTagIP),
+ typeASNCounter = (asnClsApplication|asnPrimitive|asnTagCounter),
+ typeASNGauge = (asnClsApplication|asnPrimitive|asnTagGauge),
+ typeASNTicks = (asnClsApplication|asnPrimitive|asnTagTicks),
+ typeASNOpaque = (asnClsApplication|asnPrimitive|asnTagOpaque),
+ typeASNDispString = (asnClsUniversal|asnPrimitive|asnTagOctetString),
+
+ typeASNGetRequest = (asnClsContextSpecific|asnConstructed|asnTagGetRequest),
+ typeASNGetNextRequest = (asnClsContextSpecific|asnConstructed|asnTagGetNextRequest),
+ typeASNGetResponse = (asnClsContextSpecific|asnConstructed|asnTagGetResponse),
+ typeASNSetRequest = (asnClsContextSpecific|asnConstructed|asnTagSetRequest),
+ typeASNTrap = (asnClsContextSpecific|asnConstructed|asnTagTrap)
+ };
+
+ typedef LONG asnInteger;
+ typedef LARGE_INTEGER asnInteger64;
+ typedef DWORD asnCounter;
+ typedef ULARGE_INTEGER asnCounter64;
+ typedef DWORD asnGauge;
+ typedef ULARGE_INTEGER asnGauge64;
+ typedef DWORD asnTicks;
+ typedef ULARGE_INTEGER asnTicks64;
+ struct asnDynamic {
+ UINT size;
+ LPBYTE data;
+ BOOL Allocate(UINT size) {
+ BOOL rv = Free();
+ if(size)
+ rv=rv&&(data=new BYTE[size]);
+ if(rv)
+ asnDynamic::size=size;
+ return rv;
+ }
+ BOOL Set(LPBYTE data,UINT size) {
+ BOOL rv = Allocate(size);
+ if(rv && size)
+ memmove(asnDynamic::data,data,size);
+ return rv;
+ }
+ BOOL Free() {
+ if(!size)
+ return TRUE;
+ delete data;
+ size=0;
+ data=0;
+ return TRUE;
+ }
+ void Clean() {
+ size=0;
+ data=0;
+ }
+ BOOL Copy(asnDynamic& src) {
+ BOOL rv = Free();
+ if(rv){
+ if(src.size)
+ rv=rv&&(data = new BYTE[src.size]);
+ if(rv){
+ if(size=src.size)
+ memmove(data,src.data,size);
+ }
+ }
+ return rv;
+ }
+ };
+ typedef asnDynamic asnOctetString;
+ typedef asnDynamic asnOID;
+ typedef in_addr asnIP;
+ typedef asnDynamic asnSequence;
+
+ BYTE type;
+ enum _storeType {
+ storeDynamic,
+ storeStatic
+ } storeType;
+ union {
+ asnInteger number;
+ asnInteger64 number64;
+ asnOctetString string;
+ asnOID oid;
+ asnSequence sequence;
+ asnIP ip;
+ asnCounter counter;
+ asnCounter64 counter64;
+ asnGauge gauge;
+ asnGauge64 gauge64;
+ asnTicks ticks;
+ asnTicks64 ticks64;
+ asnDynamic data;
+ } value;
+
+ CASNAny() : type(typeASNNull), storeType(storeStatic) { value.data.Clean(); }
+ CASNAny(CASNAny& src) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Copy(src); }
+ CASNAny(BYTE type) : type(type), storeType(storeStatic) { value.data.Clean(); }
+ CASNAny(BYTE type,LONG number) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,number); }
+ CASNAny(BYTE type,LONGLONG number) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,number); }
+ CASNAny(BYTE type,LPCTSTR string) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,string); }
+ CASNAny(BYTE type,LPBYTE data,UINT length) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,data,length); }
+ CASNAny(BYTE type,UINT* data,UINT size) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,(LPBYTE)data,size); }
+ CASNAny(in_addr& ip) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(ip); }
+ ~CASNAny() { Free(); }
+
+ BOOL Set(BYTE type) {
+ BOOL rv = Free();
+ CASNAny::type=type;
+ return rv;
+ }
+ BOOL Set(BYTE type,LONG number) {
+ BOOL rv = Free();
+ CASNAny::type=type;
+ value.number=number;
+ storeType=storeStatic;
+ return rv;
+ }
+ BOOL Set(BYTE type,LONGLONG number) {
+ BOOL rv = Free();
+ CASNAny::type=type;
+ value.number64.QuadPart = number;
+ storeType=storeStatic;
+ return rv;
+ }
+ BOOL Set(BYTE type,LPCTSTR string) {
+ BOOL rv = Free();
+ CASNAny::type=type;
+ rv=rv&&value.string.Set((LPBYTE)string,strlen(string)+1);
+ if(rv){
+ value.string.size--;
+ storeType=storeDynamic;
+ }
+ return rv;
+ }
+ BOOL Set(BYTE type,LPBYTE data,UINT length) {
+ BOOL rv = Free();
+ CASNAny::type=type;
+ rv=rv&&value.data.Set(data,length);
+ if(rv)
+ storeType=storeDynamic;
+ return rv;
+ }
+ BOOL Set(in_addr& ip) {
+ BOOL rv = Free();
+ memmove(&value.ip,&ip,sizeof(value.ip));
+ type=typeASNIP;
+ storeType=storeStatic;
+ return rv;
+ }
+ BOOL Free() {
+ if(storeType==storeDynamic)
+ value.data.Free();
+ else{
+ memset(&value,0,sizeof(value));
+ value.data.Clean();
+ }
+ storeType=storeStatic;
+ type=typeASNNull;
+ return TRUE;
+ }
+ BOOL Copy(CASNAny& src) {
+ BOOL rv = Free();
+ if(src.storeType==storeDynamic){
+ rv=rv&&value.data.Copy(src.value.data);
+ if(rv){
+ type=src.type;
+ storeType=src.storeType;
+ }
+ }else{
+ memmove(this,&src,sizeof(*this));
+ }
+ return rv;
+ }
+ CASNAny& operator=(CASNAny& src) {
+ VERIFY(Copy(src));
+ return *this;
+ }
+
+ // High Level
+ CString GetString() {
+ ASSERT(storeType==storeDynamic);
+ CString rv;
+ LPTSTR b = rv.GetBuffer(value.data.size+1);
+ ASSERT(b);
+ b[value.data.size]=0;
+ memmove(b,value.data.data,value.data.size);
+ rv.ReleaseBuffer();
+ return rv;
+ }
+};
+
+
+class CSNMPVarBind {
+public:
+ CASNAny name;
+ CASNAny value;
+
+ CSNMPVarBind() {}
+ CSNMPVarBind(CASNAny& name,CASNAny& value) : name(name), value(value) {}
+ CSNMPVarBind(CASNAny& name) : name(name) {}
+ CSNMPVarBind(CSNMPVarBind& src) { Copy(src); }
+ BOOL Copy(CSNMPVarBind& src) {
+ name.Copy(src.name);
+ value.Copy(src.value);
+ return TRUE;
+ }
+ CSNMPVarBind& operator=(CSNMPVarBind& src) {
+ Copy(src);
+ return *this;
+ }
+ // High level
+ BOOL IsName(UINT* prefix,UINT prefixSize,BOOL bExact=FALSE) {
+ if(name.type!=CASNAny::typeASNOID)
+ return FALSE;
+ if(name.value.oid.size<prefixSize)
+ return FALSE;
+ if(bExact && (name.value.oid.size!=prefixSize))
+ return FALSE;
+ return !memcmp(prefix,name.value.oid.data,prefixSize);
+ }
+};
+
+class CSNMPVarBindList : public CList<CSNMPVarBind,CSNMPVarBind&> {
+public:
+ CSNMPVarBind* GetVarBind(UINT* prefix,UINT prefixSize,BOOL bExact=FALSE) {
+ POSITION p = GetHeadPosition();
+ while(p){
+ CSNMPVarBind& vb = GetNext(p);
+ if(vb.IsName(prefix,prefixSize,bExact))
+ return &vb;
+ }
+ return NULL;
+ }
+};
+
+class CSNMPeer {
+public:
+ virtual BOOL Request(BYTE type,CSNMPVarBindList& in,CSNMPVarBindList& ou) = 0;
+};
+
+};
+
+#endif // __SNMPEER_H
diff --git a/shared-code/install.h b/shared-code/install.h
new file mode 100644
index 0000000..8c55ca9
--- a/dev/null
+++ b/shared-code/install.h
@@ -0,0 +1,370 @@
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+#define WIN32_EXTRALEAN
+#include <windows.h>
+#include <shlobj.h>
+#include <winver.h>
+#include <crtdbg.h>
+#include <string.h>
+#include <stdio.h>
+
+extern "C" WINSHELLAPI void WINAPI SHFree( LPVOID);
+
+template<class T> class Smart {
+public:
+ T *pT;
+
+ Smart() : pT(NULL) {}
+ Smart(int cb) : pT(new T[cb]) {}
+ Smart(T* p) : pT(p) {}
+ ~Smart() { if(pT)delete pT; }
+
+ Smart& operator=(T* p) { if(pT)delete pT; pT=p; return *this; }
+ operator T* () { return pT; }
+
+// T& operator[](int ndx) { return pT[ndx]; }
+
+ T* Detach() { T* rv = pT; pT=NULL; return rv; }
+};
+typedef Smart<char> STRING;
+
+#define APPEND_SLASH(str) if((str)[strlen(str)-1]!='\\')strcat(str,"\\")
+
+HINSTANCE theInstance;
+
+LPSTR strFETCH_REG_KEY(HKEY hRoot,LPCSTR subKey,LPCSTR val)
+{
+HKEY hkey;
+ if(RegOpenKeyEx(hRoot,subKey,0,KEY_QUERY_VALUE,&hkey)!=ERROR_SUCCESS)
+ return NULL;
+DWORD kType,cb=0;
+STRING rv;
+ if(RegQueryValueEx(hkey,val,NULL,&kType,NULL,&cb)==ERROR_SUCCESS && kType==REG_SZ){
+ rv= new char[cb];
+ _ASSERT(rv!=NULL);
+ if(RegQueryValueEx(hkey,val,NULL,&kType,(LPBYTE)(LPSTR)rv,&cb)!=ERROR_SUCCESS)
+ rv=NULL;
+ }
+ RegCloseKey(hkey);
+ return rv.Detach();
+}
+
+BOOL strSET_REG_KEY(HKEY hRoot,LPCSTR subKey,LPCSTR valName,LPCSTR val)
+{
+HKEY hkey;
+DWORD dw;
+ if(RegCreateKeyEx(hRoot,subKey,0,REG_NONE,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&hkey,&dw)!=ERROR_SUCCESS)
+ return FALSE;
+BOOL rv = (RegSetValueEx(hkey,valName,0,REG_SZ,(LPBYTE)val,strlen(val)+1)==ERROR_SUCCESS);
+ RegCloseKey(hkey);
+ return rv;
+}
+
+void MAKE_PATH(LPCSTR path)
+{
+STRING tmp(strlen(path)+1);
+LPCSTR t0=path;
+LPSTR t1=tmp;
+ while(*t0){
+ if((*t0)=='\\'){
+ *t1=0;
+ CreateDirectory(tmp,NULL);
+ }
+ *(t1++)=*(t0++);
+ }
+ *t1=0;
+ CreateDirectory(tmp,NULL);
+}
+
+BOOL ADDMENU(LPCSTR menu,LPCSTR item,LPCSTR path,LPCSTR program)
+{
+STRING stm = strFETCH_REG_KEY(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders","Programs");
+ if(!stm)
+ return FALSE;
+int pil = 1+strlen(path)+1+strlen(program)+1+1;
+STRING pi(pil);
+ strcpy(pi,path);
+ APPEND_SLASH(pi);
+ strcat(pi,program);
+int ipl = strlen(stm)+1+strlen(menu)+1+strlen(item)+4+1;
+STRING ip(ipl);
+ memmove(ip,stm,strlen(stm)+1);
+ APPEND_SLASH(ip);
+ strcat(ip,menu);
+ MAKE_PATH(ip);
+ APPEND_SLASH(ip);
+ strcat(ip,item);
+ strcat(ip,".lnk");
+IShellLink* sl = NULL;
+IPersistFile* pf = NULL;
+BOOL rv = FALSE;
+ do{
+ HRESULT hrv = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&sl);
+ if(!SUCCEEDED(hrv))
+ break;
+ sl->SetDescription(item);
+ sl->SetPath(pi);
+ hrv = sl->QueryInterface(IID_IPersistFile,(LPVOID*)&pf);
+ if(!SUCCEEDED(hrv))
+ break;
+ WORD wsz[MAX_PATH];
+ MultiByteToWideChar(CP_ACP,0,ip,-1,wsz,MAX_PATH);
+ hrv = pf->Save(wsz,TRUE);
+ if(SUCCEEDED(hrv))
+ rv=TRUE;
+ }while(FALSE);
+ if(pf)
+ pf->Release();
+ if(sl)
+ sl->Release();
+ return rv;
+}
+
+FILE* CREATE_INF_FILE(LPCSTR path,LPCSTR file)
+{
+STRING fn(strlen(path)+1+strlen(file)+1);
+ strcpy(fn,path);
+ APPEND_SLASH(fn);
+ strcat(fn,file);
+ return fopen(fn,"wt");
+}
+
+BOOL INSTALLFILE(LPCSTR res,LPCSTR path,LPCSTR file)
+{
+STRING temp(MAX_PATH);
+ if(!GetTempPath(MAX_PATH,temp)) return FALSE;
+STRING tf(MAX_PATH);
+ if(!GetTempFileName(temp,"KGI",0,tf)) return FALSE;
+HRSRC hrsrc = FindResource(NULL,res,MAKEINTRESOURCE(RT_RCDATA));
+ if(!hrsrc) return FALSE;
+DWORD sor = SizeofResource(NULL,hrsrc);
+ if(!sor) return FALSE;
+HGLOBAL hglobal = LoadResource(NULL,hrsrc);
+ if(!hglobal) return FALSE;
+LPVOID lpv = LockResource(hglobal);
+ if(!lpv) return FALSE;
+HANDLE hf = CreateFile(tf,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY,NULL);
+ if(!hf) return FALSE;
+DWORD written = 0;
+ if(!WriteFile(hf,lpv,sor,&written,NULL) || written!=sor){
+ CloseHandle(hf);
+ return FALSE;
+ }
+ CloseHandle(hf);
+STRING toKill(strlen(tf)+1);
+ strcpy(toKill,tf);
+ for(int tmp=strlen(tf)-1;tmp>0 && ((tf[tmp])!='\\');tmp--);
+ if(tf[tmp]=='\\')
+ tf[tmp++]=0;
+STRING nothing(_MAX_PATH);
+UINT nothingLength=_MAX_PATH;
+ if(VerInstallFile(0,&tf[tmp],(LPSTR)file,tf,(LPSTR)path,NULL,nothing,&nothingLength)){
+ DeleteFile(toKill);
+ return FALSE;
+ }
+ DeleteFile(toKill);
+ return TRUE;
+}
+
+LPCSTR pdTitle, pdPrompt;
+char pdPath[_MAX_PATH];
+BOOL CALLBACK pathDlgProc(HWND hwnd,UINT uMsg,WPARAM wP,LPARAM lP)
+{
+ switch(uMsg){
+ case WM_INITDIALOG:
+ SetWindowText(hwnd,pdTitle);
+ SetDlgItemText(hwnd,IDC_PROMPT,pdPrompt);
+ SetDlgItemText(hwnd,IDC_PATH,pdPath);
+ SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
+ return 1;
+ case WM_COMMAND:
+ switch(LOWORD(wP)){ // ID
+ case IDC_BROWSE:
+ switch(HIWORD(wP)){
+ case BN_CLICKED:
+ {
+ BROWSEINFO bi;
+ memset(&bi,0,sizeof(bi));
+ bi.hwndOwner=hwnd;
+ bi.pszDisplayName=pdPath;
+ bi.lpszTitle="Select Folder..";
+ bi.ulFlags=BIF_RETURNONLYFSDIRS;
+ LPITEMIDLIST lpidl=SHBrowseForFolder(&bi);
+ if(lpidl){
+ SHGetPathFromIDList(lpidl,pdPath);
+ SHFree(lpidl);
+ SetDlgItemText(hwnd,IDC_PATH,pdPath);
+ }
+ }
+ return 1;
+ }
+ break;
+ case IDOK:
+ switch(HIWORD(wP)){
+ case BN_CLICKED:
+ if(GetDlgItemText(hwnd,IDC_PATH,pdPath,sizeof(pdPath)))
+ EndDialog(hwnd,IDOK);
+ else
+ // *** Error message
+ EndDialog(hwnd,IDCANCEL);
+ return 1;
+ }
+ break;
+ case IDCANCEL:
+ switch(HIWORD(wP)){
+ case BN_CLICKED:
+ EndDialog(hwnd,IDCANCEL);
+ return 1;
+ }
+ break;
+ };
+ break;
+ }
+ return 0;
+}
+
+LPSTR REQUESTPATH(LPCSTR title,LPCSTR prompt,LPCSTR defPath)
+{
+ pdTitle=title;pdPrompt=prompt;
+ strcpy(pdPath,defPath);
+ if(DialogBox(NULL,MAKEINTRESOURCE(IDD_PATH),NULL/*Parent*/,(DLGPROC)&pathDlgProc)!=IDOK)
+ return NULL;
+STRING rv(strlen(pdPath)+1);
+ strcpy(rv,pdPath);
+ return rv.Detach();
+}
+
+HKEY uninstallKey(LPCSTR regKey) {
+ STRING rk(100+strlen(regKey)+1);
+ sprintf(rk,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s",regKey);
+ HKEY rv = NULL;
+ DWORD dw;
+ if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,rk,0,REG_NONE,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&rv,&dw)!=ERROR_SUCCESS)
+ return NULL;
+ return rv;
+}
+
+BOOL REG_UNINSTALL_COMMAND(LPCSTR regKey,LPCSTR dName,LPCSTR iPath,LPCSTR iFile,LPCSTR iSection)
+{
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ BOOL rv=FALSE;
+ do{
+ if(RegSetValueEx(hKey,"DisplayName",0,REG_SZ,(LPBYTE)dName,strlen(dName)+1)!=ERROR_SUCCESS)
+ break;
+ STRING us(50+strlen(iPath)+1+strlen(iFile)+strlen(iSection)+1);
+ strcpy(us,"RunDll32 setupapi.dll,InstallHinfSection ");
+ strcat(us,iSection);
+ strcat(us," 132 ");
+ strcat(us,iPath);
+ APPEND_SLASH(us);
+ strcat(us,iFile);
+ if(RegSetValueEx(hKey,"UninstallString",0,REG_SZ,(LPBYTE)(LPCSTR)us,strlen(us)+1)!=ERROR_SUCCESS)
+ break;
+ rv=TRUE;
+ }while(FALSE);
+ RegCloseKey(hKey);
+ return rv;
+}
+BOOL REG_UNINSTALL_ICON(LPCSTR regKey,LPCSTR path,LPCSTR file,int n) {
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ STRING uis(strlen(path)+1+strlen(file)+7);
+ strcpy(uis,path);
+ APPEND_SLASH(uis);
+ strcat(uis,file);
+ char tmp[8];
+ sprintf(tmp,";%d",n);
+ strcat(uis,tmp);
+ BOOL rv = TRUE;
+ if(RegSetValueEx(hKey,"DisplayIcon",0,REG_SZ,(LPBYTE)(LPCSTR)uis,strlen(uis)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ RegCloseKey(hKey);
+ return rv;
+}
+BOOL REG_UNINSTALL_COMMENT(LPCSTR regKey,LPCSTR comment) {
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ BOOL rv = TRUE;
+ if(RegSetValueEx(hKey,"lComment",0,REG_SZ,(LPBYTE)comment,strlen(comment)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ RegCloseKey(hKey);
+ return rv;
+}
+BOOL REG_UNINSTALL_VERSION(LPCSTR regKey,LPCSTR version) {
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ BOOL rv = TRUE;
+ if(RegSetValueEx(hKey,"DisplayVersion",0,REG_SZ,(LPBYTE)version,strlen(version)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ RegCloseKey(hKey);
+ return rv;
+}
+BOOL REG_UNINSTALL_LOCATION(LPCSTR regKey,LPCSTR location) {
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ BOOL rv = TRUE;
+ if(RegSetValueEx(hKey,"InstallLocation",0,REG_SZ,(LPBYTE)location,strlen(location)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ RegCloseKey(hKey);
+ return rv;
+}
+BOOL REG_UNINSTALL_PUBLISHER(LPCSTR regKey,LPCSTR publisher) {
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ BOOL rv = TRUE;
+ if(RegSetValueEx(hKey,"Publisher",0,REG_SZ,(LPBYTE)publisher,strlen(publisher)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ RegCloseKey(hKey);
+ return rv;
+}
+BOOL REG_UNINSTALL_URLS(LPCSTR regKey,LPCSTR about,LPCSTR update) {
+ HKEY hKey = uninstallKey(regKey);
+ if(!hKey)
+ return FALSE;
+ BOOL rv = TRUE;
+ if(RegSetValueEx(hKey,"URLInfoAbout",0,REG_SZ,(LPBYTE)about,strlen(about)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ if(RegSetValueEx(hKey,"URLUpdateInfo",0,REG_SZ,(LPBYTE)update,strlen(update)+1)!=ERROR_SUCCESS)
+ rv = FALSE;
+ RegCloseKey(hKey);
+ return rv;
+}
+
+#define INF_FILE_HEADER(i) fprintf(i,"[Version]\nSignature=\"$CHICAGO$\"\n\n")
+#define INF_FILE_SECTION(i,s) fprintf(i,"\n[%s]\n",s)
+#define INF_UNINSTALL_REG(i,p) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s\nHKLM,Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s,DisplayName\nHKLM,Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s,UninstallString\n",p,p,p)
+#define INF_MENU_GROUP(i,n,m) fprintf(i,"setup.ini, progman.groups,,\"group%d=%s\"\n",n,m)
+#define INF_MENU_ITEM(i,n,m) fprintf(i,"setup.ini, group%d,, \"\"\"%s\"\"\"\n",n,m);
+#define INF_REMOVE_ROOT(i,g,r) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\DeleteFiles\\%s,,,\"%s\"\n",g,r)
+#define INF_REMOVE_FILE(i,g,f) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\DeleteFiles\\%s,%s,,\"%s\"\n",g,f,f)
+#define INF_REMOVE_HELP_FILE(i,g,f) {INF_REMOVE_FILE(i,g,f".hlp");INF_REMOVE_FILE(i,g,f".cnt");INF_REMOVE_FILE(i,g,f".GID");INF_REMOVE_FILE(i,g,f".FTS");}
+
+LPSTR GET_SHORT_PATH(LPCSTR path)
+{
+char tmp;
+DWORD len = GetShortPathName(path,&tmp,1);
+ if(!len)
+ return NULL;
+STRING rv(len+1);
+ if(!GetShortPathName(path,rv,len+1))
+ return NULL;
+ return rv.Detach();
+}
+
+BOOL Install(void);
+
+int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)
+{
+ theInstance=hInstance;
+ CoInitialize(NULL);
+ Install();
+ CoUninitialize();
+ return 0;
+}
diff --git a/shared-code/ip_icmp.h b/shared-code/ip_icmp.h
new file mode 100644
index 0000000..acaf7e9
--- a/dev/null
+++ b/shared-code/ip_icmp.h
@@ -0,0 +1,91 @@
+#ifndef IP_ICMPHEADER
+
+#define IP_ICMPHEADER
+
+struct icmp {
+ BYTE icmp_type;
+ BYTE icmp_code;
+ WORD icmp_cksum;
+ WORD icmp_id;
+ WORD icmp_seq;
+ char icmp_data[1];
+};
+
+#define SIZE_ICMP_HDR 8
+#define SIZE_TIME_DATA 8
+
+struct ip {
+ BYTE ip_hl:4, /* header length */
+ ip_v:4; /* version */
+ BYTE ip_tos; /* type of service */
+ short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ short ip_off; /* fragment offset field */
+ BYTE ip_ttl; /* time to live */
+ BYTE ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ struct in_addr ip_src,ip_dst; /* source and dest address */
+};
+
+#define ICMP_ECHOREPLY 0 /* echo reply */
+#define ICMP_UNREACH 3 /* dest unreachable, codes: */
+#define ICMP_UNREACH_NET 0 /* bad net */
+#define ICMP_UNREACH_HOST 1 /* bad host */
+#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
+#define ICMP_UNREACH_PORT 3 /* bad port */
+#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
+#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
+#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
+#define ICMP_REDIRECT 5 /* shorter route, codes: */
+#define ICMP_REDIRECT_NET 0 /* for network */
+#define ICMP_REDIRECT_HOST 1 /* for host */
+#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
+#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
+#define ICMP_ECHO 8 /* echo service */
+#define ICMP_TIMXCEED 11 /* time exceeded, code: */
+#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
+#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
+#define ICMP_PARAMPROB 12 /* ip header bad */
+#define ICMP_TSTAMP 13 /* timestamp request */
+#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
+#define ICMP_IREQ 15 /* information request */
+#define ICMP_IREQREPLY 16 /* information reply */
+#define ICMP_MASKREQ 17 /* address mask request */
+#define ICMP_MASKREPLY 18 /* address mask reply */
+
+#define ICMP_MAXTYPE 18
+
+#define ICMP_MINLEN 8 /* abs minimum */
+#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
+#define ICMP_MASKLEN 12 /* address mask */
+#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
+#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
+
+#define STNORM 0
+
+/* Definition of the lowest telnet byte following an IAC byte */
+#define LOW_TEL_OPT 236
+
+#define TEL_EOF 236
+#define SUSP 237
+#define ABORT 238
+
+#define SE 240
+#define NOP 241
+#define DM 242
+#define BREAK 243
+#define IP 244
+#define AO 245
+#define AYT 246
+#define EC 247
+#define EL 248
+#define GOAHEAD 249
+#define SB 250
+#define WILL 251
+#define WONT 252
+#define DO 253
+#define DONT 254
+#define IAC 255
+
+#endif
+
diff --git a/shared-code/kHelpers.h b/shared-code/kHelpers.h
new file mode 100644
index 0000000..209c6b0
--- a/dev/null
+++ b/shared-code/kHelpers.h
@@ -0,0 +1,159 @@
+#ifndef __KHELPERS_H
+#define __KHELPERS_H
+
+#include <shlobj.h>
+
+extern "C" WINSHELLAPI void WINAPI SHFree( LPVOID);
+
+namespace Klever {
+
+ inline BOOL BrowseForFolder(CString& folder,LPCTSTR title=NULL,CWnd* pParent=NULL) {
+ BROWSEINFO bi;
+ memset(&bi,0,sizeof(bi));
+ if(pParent)
+ bi.hwndOwner=pParent->GetSafeHwnd();
+ CString rv;
+ bi.pszDisplayName=rv.GetBuffer(MAX_PATH);
+ bi.lpszTitle=title;
+ bi.ulFlags=BIF_RETURNONLYFSDIRS;
+ LPITEMIDLIST lpidl = SHBrowseForFolder(&bi);
+ if(lpidl){
+ SHGetPathFromIDList(lpidl,bi.pszDisplayName);
+ SHFree(lpidl);
+ rv.ReleaseBuffer();
+ folder=rv;
+ return TRUE;
+ }
+ rv.ReleaseBuffer();
+ return FALSE;
+ }
+ inline BOOL BrowseForFolder(CString& folder,UINT idTitle,CWnd* pParent=NULL) {
+ CString title;
+ VERIFY(title.LoadString(idTitle));
+ return BrowseForFolder(folder,title,pParent);
+ }
+ inline CString GluePathAndFile(LPCTSTR path,LPCTSTR file) {
+ CString rv = path;
+ while((!rv.IsEmpty()) && rv[rv.GetLength()-1]=='\\')
+ rv=rv.Left(rv.GetLength()-1);
+ rv+='\\';
+ while(*file && *file=='\\')
+ file++;
+ rv+=file;
+ return rv;
+ }
+ inline UINT TokenizeString(CStringList& rv,LPCTSTR string,LPCTSTR delimiter) {
+ CString s = string;
+ int found;
+ int delength = strlen(delimiter);
+ int rvc = 0;
+ while((found=s.Find(delimiter))>=0){
+ rv.AddTail(s.Left(found));
+ rvc++;
+ s=s.Mid(found+delength);
+ }
+ if(!s.IsEmpty()){
+ rv.AddTail(s);
+ rvc++;
+ }
+ return rvc;
+ }
+ inline BOOL LogRecord(LPCTSTR logFile,LPCTSTR logRecord) {
+ try{
+ CFile f(logFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyWrite);
+ f.SeekToEnd();
+ CString s = CTime::GetCurrentTime().Format("[%c] ")+logRecord+"\r\n";
+ f.Write((LPCTSTR)s,s.GetLength());
+ }catch(CException* e){
+ e->Delete();
+ return FALSE;
+ }
+ return TRUE;
+ }
+ inline BOOL ReadString(CFile* file,CString& rv) {
+ rv.Empty();
+ int nBuffer = 256;
+ TCHAR* ch = rv.GetBuffer(nBuffer);
+ int nPos = 0;
+ BOOL bRV = FALSE;
+ for(;;){
+ TCHAR c;
+ try{
+ if(file->Read(&c,sizeof(c))!=sizeof(c))
+ break;
+ bRV=TRUE;
+ }catch(CException* e){
+ e->Delete();
+ TRACE0("Exception in ReadString\n");
+ return FALSE;
+ }
+ if(nPos>=(nBuffer-1)){
+ rv.ReleaseBuffer();
+ ch = rv.GetBuffer(nBuffer=nBuffer+256);
+ ASSERT(ch);
+ }
+ if(c=='\n')
+ break;
+ ch[nPos++]=c;
+ }
+ ch[nPos]=0;
+ for(;;){
+ nPos--;
+ if(nPos<0)
+ break;
+ if(ch[nPos]!='\r')
+ break;
+ ch[nPos]=0;
+ }
+ rv.ReleaseBuffer();
+ rv.FreeExtra();
+ return bRV;
+ }
+
+ inline int LoadStringList(CStringList& list,LPCTSTR section) {
+ CString n;
+ list.RemoveAll();
+ CWinApp* app = AfxGetApp();
+ ASSERT(app);
+ for(int tmp=0;;tmp++){
+ n.Format("%d",tmp);
+ CString str = app->GetProfileString(section,n,NULL);
+ if(str.IsEmpty())
+ break;
+ list.AddTail(str);
+ }
+ return tmp;
+ }
+ inline int SaveStringList(CStringList& list,LPCTSTR section) {
+ CString n;
+ CWinApp* app = AfxGetApp();
+ ASSERT(app);
+ POSITION p = list.GetHeadPosition();
+ for(int tmp=0;p;tmp++){
+ n.Format("%d",tmp);
+ app->WriteProfileString(section,n,list.GetNext(p));
+ }
+ n.Format("%d",tmp);
+ app->WriteProfileString(section,n,NULL);
+ return tmp;
+ }
+
+ inline BOOL WriteProfileString(LPCTSTR section,LPCTSTR entry,LPCTSTR str) {
+ CWinApp* app = AfxGetApp();
+ return app->WriteProfileBinary(section,entry,(LPBYTE)str,strlen(str)+1);
+ }
+ inline CString GetProfileString(LPCTSTR section,LPCTSTR entry,LPCTSTR defval) {
+ CWinApp* app = AfxGetApp();
+ LPBYTE pData;
+ UINT nCount;
+ CString rv = defval;
+ if(app->GetProfileBinary(section,entry,&pData,&nCount)){
+ rv = (LPCTSTR)pData;
+ delete pData;
+ }
+ return rv;
+ }
+
+};
+
+#endif // __KHELPERS_H
diff --git a/shared-code/kICMP.cpp b/shared-code/kICMP.cpp
new file mode 100644
index 0000000..09a8f94
--- a/dev/null
+++ b/shared-code/kICMP.cpp
@@ -0,0 +1,300 @@
+#include "../stdafx.h"
+#include "kICMP.h"
+
+CICMP::_mechanismus CICMP::m_mechanismus = CICMP::_icmpUndetermined;
+
+BOOL CICMPDll::Initialize()
+{
+ if(m_hICMP!=INVALID_HANDLE_VALUE || m_hICMPDLL)
+ Deinitialize();
+ m_hICMPDLL = ::LoadLibraryEx("ICMP",NULL,0);
+ if(!m_hICMPDLL)
+ return FALSE;
+ *(FARPROC*)&m_icmpCF = ::GetProcAddress(m_hICMPDLL,"IcmpCreateFile");
+ *(FARPROC*)&m_icmpSE = ::GetProcAddress(m_hICMPDLL,"IcmpSendEcho");
+ *(FARPROC*)&m_icmpCH = ::GetProcAddress(m_hICMPDLL,"IcmpCloseHandle");
+ if(!(m_icmpCF && m_icmpSE && m_icmpCH)){
+ Deinitialize(); return FALSE;
+ }
+ m_hICMP = (*m_icmpCF)();
+ if(m_hICMP==INVALID_HANDLE_VALUE){
+ Deinitialize(); return FALSE;
+ }
+ TRACE0("ICMP-DLL Initialized\n");
+ return TRUE;
+}
+void CICMPDll::Deinitialize()
+{
+ if(m_hICMPDLL){
+ if(m_hICMP!=INVALID_HANDLE_VALUE && m_icmpCH)
+ (*m_icmpCH)(m_hICMP);
+ ::FreeLibrary(m_hICMPDLL); m_hICMPDLL = NULL;
+ m_icmpCF = NULL;
+ m_icmpSE = NULL;
+ m_icmpCH = NULL;
+ }
+ m_hICMP=INVALID_HANDLE_VALUE;
+ if(m_sizeOut && m_bsOut){
+ delete m_bsOut;
+ m_bsOut = NULL; m_sizeOut = 0;
+ }
+ if(m_sizeIn && m_bsIn){
+ delete m_bsIn;
+ m_bsIn = NULL; m_sizeIn = 0;
+ }
+}
+
+LONG CICMPDll::Ping(const in_addr host,const UINT packetSize,
+ const UINT timeOut,LPINT pStatus)
+{
+ if(!(m_hICMP && m_hICMPDLL && m_icmpSE)){
+ if(pStatus)
+ (*pStatus) = icmpNotInitialized;
+ return -1;
+ }
+ VERIFY(AdjustBuffers(packetSize));
+IPINFO ipi;
+ memset(&ipi,0,sizeof(ipi));
+ ipi.Ttl = 30;
+ for(UINT tmp=0;tmp<packetSize;tmp++)
+ m_bsOut[tmp]=tmp&0xFF;
+LPICMPECHO pRep = (LPICMPECHO)m_bsIn;
+ pRep->Status = 0xFFFFFFFFl;
+ if((*m_icmpSE)(m_hICMP,host.s_addr,m_bsOut,packetSize,
+ &ipi,pRep,m_sizeIn,timeOut))
+ TRACE0("ICMP-SendEcho succeeded\n");
+ else
+ TRACE0("ICMP-SendEcho failed\n");
+LONG lrv = -1;
+INT rv = ipUnknown;
+ switch(pRep->Status){
+ case IP_SUCCESS:
+ lrv = pRep->RTTime; rv = ipSuccess;
+ break;
+ case IP_BUF_TOO_SMALL: rv = ipBuffTooSmall; break;
+ case IP_DEST_NET_UNREACHABLE: rv = ipDestNetUnreachable; break;
+ case IP_DEST_HOST_UNREACHABLE: rv = ipDestHostUnreachable; break;
+ case IP_DEST_PROT_UNREACHABLE: rv = ipDestProtUnreachable; break;
+ case IP_DEST_PORT_UNREACHABLE: rv = ipDestPortUnreachable; break;
+ case IP_NO_RESOURCES: rv = ipNoResources; break;
+ case IP_BAD_OPTION: rv = ipBadOption; break;
+ case IP_HW_ERROR: rv = ipHWError; break;
+ case IP_PACKET_TOO_BIG: rv = ipPacketTooBig; break;
+ case IP_REQ_TIMED_OUT: rv = ipTimeOut; break;
+ case IP_BAD_REQ: rv = ipBadRequest; break;
+ case IP_BAD_ROUTE: rv = ipBadRoute; break;
+ case IP_TTL_EXPIRED_TRANSIT: rv = ipTTLExpiredInTransit; break;
+ case IP_TTL_EXPIRED_REASSEM: rv = ipTTLExpiredInReasm; break;
+ case IP_PARAM_PROBLEM: rv = ipParamProblem; break;
+ case IP_SOURCE_QUENCH: rv = ipSourceQuench; break;
+ case IP_OPTION_TOO_BIG: rv = ipOptionTooBig; break;
+ case IP_BAD_DESTINATION: rv = ipBadDest; break;
+ }
+ if(pStatus)
+ (*pStatus)=rv;
+ return lrv;
+}
+
+BOOL CICMPDll::AdjustBuffers(UINT packetSize)
+{
+ if(!packetSize)
+ packetSize=1;
+ if(packetSize>m_sizeOut){
+ if(m_sizeOut && m_bsOut)
+ delete m_bsOut;
+ m_bsOut = new BYTE[m_sizeOut=packetSize];
+ if(!m_bsOut)
+ return FALSE;
+ }
+UINT sin = sizeof(ICMPECHO)+SIZE_ICMP_HDR+packetSize;
+ if(sin>m_sizeIn){
+ if(m_sizeIn && m_bsIn)
+ delete m_bsIn;
+ m_bsIn = new BYTE[m_sizeIn=sin];
+ if(!m_bsIn)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+WORD CICMPWS::m_icmpSeq = 0;
+
+BOOL CICMPWS::Initialize()
+{
+ if(m_socket!=INVALID_SOCKET)
+ Deinitialize();
+ m_socket = socket(AF_INET,SOCK_RAW,1/*ICMP*/);
+ if(m_socket==INVALID_SOCKET)
+ return FALSE;
+ TRACE0("ICMP-WS Initialized\n");
+ return TRUE;
+}
+void CICMPWS::Deinitialize()
+{
+ if(m_socket!=INVALID_SOCKET){
+ closesocket(m_socket);
+ m_socket=INVALID_SOCKET;
+ }
+ if(m_sizeOut && m_bsOut){
+ delete m_bsOut;
+ m_bsOut = NULL; m_sizeOut = 0;
+ }
+ if(m_sizeIn && m_bsIn){
+ delete m_bsIn;
+ m_bsIn = NULL; m_sizeIn = 0;
+ }
+}
+LONG CICMPWS::Ping(const in_addr host,const UINT packetSize,
+ const UINT timeOut,LPINT pStatus)
+{
+ if(m_socket==INVALID_SOCKET){
+ if(pStatus)
+ (*pStatus)=icmpNotInitialized;
+ }
+ VERIFY(AdjustBuffers(packetSize));
+icmp* pPacket = (icmp*)m_bsOut;
+ memset(pPacket,0,m_sizeOut);
+ pPacket->icmp_type = ICMP_ECHO;
+ pPacket->icmp_seq = m_icmpSeq++;
+ pPacket->icmp_id = (WORD)(::GetCurrentThreadId()&0xFFFF);
+ for(UINT tmp=0;tmp<packetSize;tmp++)
+ pPacket->icmp_data[tmp]=tmp&0xFF;
+ pPacket->icmp_cksum = cksum(pPacket,SIZE_ICMP_HDR+packetSize);
+sockaddr_in to;
+ memset(&to,0,sizeof(to));
+ to.sin_addr.s_addr = host.s_addr;
+ to.sin_family = AF_INET;
+ if(sendto(m_socket,(char*)pPacket,SIZE_ICMP_HDR+packetSize,0,
+ (SOCKADDR*)&to,sizeof(to)) != (int)(SIZE_ICMP_HDR+packetSize)){
+ TRACE1("sendto: %lu\n",WSAGetLastError());
+ if(pStatus)
+ (*pStatus)=icmpSocketError;
+ return -1;
+ }
+DWORD sentTime = ::GetTickCount();
+sockaddr_in from;
+ memset(&from,0,sizeof(from));
+ from.sin_family=AF_INET;
+ from.sin_addr.s_addr=INADDR_ANY;
+fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(m_socket,&fds);
+long lrv = -1;
+INT rv = ipTimeOut;
+ for(;;){
+ DWORD ct = ::GetTickCount();
+ if((ct-sentTime)>=timeOut){
+ TRACE0("Timeout\n");
+ break;
+ }
+ timeval tv = {
+ (timeOut-ct+sentTime)/1000,
+ (timeOut-ct+sentTime)%1000
+ }; // tv_sec, tv_usec (secs,microsecs)
+ if(!select(m_socket,&fds,NULL,NULL,&tv)){
+ TRACE1("select: %d\n",WSAGetLastError());
+ break;
+ }
+ DWORD rtime = ::GetTickCount();
+ ASSERT(FD_ISSET(m_socket,&fds));
+ int fl = sizeof(from);
+ int rb = recvfrom(m_socket,(char*)m_bsIn,m_sizeIn,0,(SOCKADDR*)&from,&fl);
+ ip* pIP = (ip*)m_bsIn;
+ icmp* pICMP = (icmp*)&m_bsIn[sizeof(ip)];
+ if(pICMP->icmp_id!=pPacket->icmp_id)
+ continue;
+ if(pICMP->icmp_seq!=pPacket->icmp_seq)
+ continue;
+ if(from.sin_addr.s_addr!=host.s_addr)
+ continue;
+ if(pICMP->icmp_type==ICMP_ECHOREPLY){
+ lrv=rtime-sentTime;
+ rv=ipSuccess;
+ break;
+ }
+ rv = ipUnknown; // ***
+ break;
+ }
+ if(pStatus)
+ (*pStatus)=rv;
+ return lrv;
+}
+
+BOOL CICMPWS::AdjustBuffers(UINT packetSize)
+{
+ if(!packetSize)
+ packetSize=0;
+UINT osize = packetSize+SIZE_ICMP_HDR;
+ if(m_sizeOut<osize){
+ if(m_sizeOut && m_bsOut)
+ delete m_bsOut;
+ m_bsOut = new BYTE[m_sizeOut=osize];
+ if(!m_bsOut)
+ return FALSE;
+ }
+UINT isize = osize+sizeof(ip);
+ if(m_sizeIn<isize){
+ if(m_sizeIn && m_bsIn)
+ delete m_bsIn;
+ m_bsIn = new BYTE[m_sizeIn=isize];
+ if(!m_bsIn)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+WORD CICMPWS::cksum(LPVOID data,int count)
+{
+long lSum = 0;
+WORD *pData = (WORD*)data;
+ while(count>0){
+ if(count>1){
+ lSum+=*(pData++);
+ count-=2;
+ }else{
+ lSum+=((WORD)*(BYTE*)pData)&0xFF;
+ count--;
+ }
+ }
+ lSum = (lSum&0xFFFF)+(lSum>>16);
+ lSum += (lSum>>16);
+ return (~lSum)&0xFFFF;
+}
+
+CICMP* CICMP::CreateICMP()
+{
+ if(m_mechanismus==_icmpUndetermined)
+ GuessMechanismus();
+ switch(m_mechanismus){
+ case _icmpWinsock:
+ return new CICMPWS;
+ break;
+ case _icmpDLL:
+ return new CICMPDll;
+ break;
+ }
+ return NULL;
+}
+
+void CICMP::GuessMechanismus()
+{
+ m_mechanismus=_icmpUndetermined;
+SOCKET testSocket = socket(AF_INET,SOCK_RAW,1);
+ if(testSocket!=INVALID_SOCKET){
+ closesocket(testSocket);
+ m_mechanismus=_icmpWinsock;
+ }else{
+ HINSTANCE hICMP = ::LoadLibraryEx("ICMP",NULL,0);
+ if(!hICMP)
+ return;
+ BOOL isThere = (
+ ::GetProcAddress(hICMP,"IcmpCreateFile")
+ && ::GetProcAddress(hICMP,"IcmpSendEcho")
+ && ::GetProcAddress(hICMP,"IcmpCloseHandle")
+ );
+ ::FreeLibrary(hICMP);
+ if(isThere)
+ m_mechanismus=_icmpDLL;
+ }
+} \ No newline at end of file
diff --git a/shared-code/kICMP.h b/shared-code/kICMP.h
new file mode 100644
index 0000000..7a5ceaa
--- a/dev/null
+++ b/shared-code/kICMP.h
@@ -0,0 +1,80 @@
+#ifndef __KICMP_H
+#define __KICMP_H
+
+class CICMP {
+ enum _mechanismus {
+ _icmpUndetermined = -1,
+ _icmpWinsock = 0, _icmpDLL
+ };
+static _mechanismus m_mechanismus;
+static void GuessMechanismus();
+public:
+static
+ CICMP* CreateICMP();
+
+ enum {
+ ipSuccess = 0,
+ ipBuffTooSmall, ipDestNetUnreachable, ipDestHostUnreachable,
+ ipDestProtUnreachable, ipDestPortUnreachable, ipNoResources,
+ ipBadOption, ipHWError, ipPacketTooBig, ipTimeOut, ipBadRequest,
+ ipBadRoute, ipTTLExpiredInTransit, ipTTLExpiredInReasm,
+ ipParamProblem, ipSourceQuench, ipOptionTooBig, ipBadDest,
+ ipUnknown = -1,
+ icmpNotInitialized = -2,
+ icmpSocketError = -3
+ };
+
+ virtual BOOL Initialize() = 0;
+ virtual void Deinitialize() = 0;
+
+ virtual LONG Ping(const in_addr host,const UINT packetSize=0,
+ const UINT timeOut=10000,LPINT pStatus=NULL) = 0;
+};
+
+class CICMPDll : public CICMP {
+ HANDLE (WINAPI *m_icmpCF)(VOID);
+ BOOL (WINAPI *m_icmpSE)(HANDLE,ULONG,LPVOID,WORD,
+ PIPINFO,LPVOID,DWORD,DWORD);
+ BOOL (WINAPI *m_icmpCH)(HANDLE);
+public:
+ HINSTANCE m_hICMPDLL;
+ HANDLE m_hICMP;
+ LPBYTE m_bsIn, m_bsOut;
+ UINT m_sizeIn, m_sizeOut;
+
+ CICMPDll() : m_hICMP(INVALID_HANDLE_VALUE), m_hICMPDLL(NULL),
+ m_bsIn(NULL), m_bsOut(NULL), m_sizeIn(0), m_sizeOut(0) {}
+ virtual ~CICMPDll() { Deinitialize(); }
+
+ virtual BOOL Initialize();
+ virtual void Deinitialize();
+
+ virtual LONG Ping(const in_addr host,const UINT packetSize=0,
+ const UINT timeOut=10000,LPINT pStatus=NULL);
+
+ BOOL AdjustBuffers(UINT packetSize=0);
+};
+
+class CICMPWS : public CICMP {
+static
+ WORD m_icmpSeq;
+public:
+ SOCKET m_socket;
+ LPBYTE m_bsIn, m_bsOut;
+ UINT m_sizeIn, m_sizeOut;
+
+ CICMPWS() : m_socket(INVALID_SOCKET), m_bsIn(NULL), m_bsOut(NULL),
+ m_sizeIn(0), m_sizeOut(0) {}
+ virtual ~CICMPWS() { Deinitialize(); }
+
+ virtual BOOL Initialize();
+ virtual void Deinitialize();
+
+ virtual LONG Ping(const in_addr host,const UINT packetSize=0,
+ const UINT timeOut=10000,LPINT pStatus=NULL);
+
+ BOOL AdjustBuffers(UINT packetSize=0);
+ WORD cksum(LPVOID data,int count);
+};
+
+#endif // __KICMP_H \ No newline at end of file
diff --git a/shared-code/kinhelp.xsl b/shared-code/kinhelp.xsl
new file mode 100644
index 0000000..0bb384a
--- a/dev/null
+++ b/shared-code/kinhelp.xsl
@@ -0,0 +1,250 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+ <xsl:output
+ method="text"
+ encoding="us-ascii"/>
+ <xsl:strip-space elements="*"/>
+
+ <xsl:template match="winhelp">
+ <xsl:text>{\rtf1\ansi</xsl:text>
+ <xsl:text>&#xA;@{\footnote</xsl:text>
+ <xsl:text>&#xA;THIS FILE WAS AUTOMATICALLY GENERATED FROM XML DOCUMENT.</xsl:text>
+ <xsl:text>&#xA;DO NOT MODIFY THIS FILE DIRECTLY. EDIT XML DOCUMENT INSTEAD</xsl:text>
+ <xsl:text>&#xA;}&#xA;</xsl:text>
+ <xsl:call-template name="fonttbl"/>
+ <xsl:call-template name="colortbl"/>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="topic">
+ <xsl:text>&#xA;\pard\plain</xsl:text>
+ <xsl:if test="descendant::*[ (@scroll='no') and
+ count(preceding-sibling::*[not(@scroll='no') and (name()!='a' and @name)])=0] ">
+ <xsl:text>\keepn</xsl:text>
+ </xsl:if>
+ <xsl:if test="@id">
+ <xsl:text>&#xA;#{\footnote </xsl:text>
+ <xsl:value-of select="@id"/>
+ <xsl:text>}</xsl:text>
+ </xsl:if>
+ <xsl:if test="@title">
+ <xsl:text>&#xA;${\footnote </xsl:text>
+ <xsl:value-of select="@title"/>
+ <xsl:text>}</xsl:text>
+ </xsl:if>
+ <xsl:if test="@keywords">
+ <xsl:text>&#xA;K{\footnote </xsl:text>
+ <xsl:value-of select="@keywords"/>
+ <xsl:text>}</xsl:text>
+ </xsl:if>
+ <xsl:apply-templates/>
+ <xsl:text>&#xA;\page&#xA;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="a[@name]">
+ <xsl:text>{#{\footnote </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>}}</xsl:text>
+ </xsl:template>
+ <xsl:template match="a[@href]">
+ <xsl:call-template name="hyperref">
+ <xsl:with-param name="href" select="@href"/>
+ <xsl:with-param name="inset"><xsl:apply-templates/></xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="hyperref">
+ <xsl:param name="href"/>
+ <xsl:param name="inset"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($href,'http:') or starts-with($href,'mailto:') or
+ starts-with($href,'ftp:')">
+ <xsl:text>{\uldb </xsl:text>
+ <xsl:value-of select="$inset"/>
+ <xsl:text>}{\v %!ExecFile("</xsl:text>
+ <xsl:value-of select="$href"/>
+ <xsl:text>")}</xsl:text>
+ </xsl:when>
+ <xsl:when test="starts-with($href,'#')">
+ <xsl:text>{\uldb </xsl:text>
+ <xsl:value-of select="$inset"/>
+ <xsl:text>}{\v </xsl:text>
+ <xsl:value-of select="substring($href,2)"/>
+ <xsl:text>}</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>Warining: Unqualified hyper-reference. Using as help-internal</xsl:message>
+ <xsl:text>{\uldb </xsl:text>
+ <xsl:value-of select="$inset"/>
+ <xsl:text>}{\v </xsl:text>
+ <xsl:value-of select="$href"/>
+ <xsl:text>}</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="heading">
+ <xsl:text>&#xA;</xsl:text>
+ <xsl:if test="@scroll!='no'">
+ <xsl:text>\pard </xsl:text>
+ </xsl:if>
+ <xsl:text>{ \f1\fs18\b\sb120 </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="p">
+ <xsl:text>&#xA;\par\sa120\sb120\qj</xsl:text>
+ <xsl:if test="@scroll!='no'">
+ <xsl:text>\pard</xsl:text>
+ </xsl:if>
+ <xsl:text> \f1\fs18\sb120 </xsl:text>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="note">
+ <xsl:text>&#xA;\par\sa120\sb120\qj\f1\fs16 </xsl:text>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="dedication">
+ <xsl:text>&#xA;\par\sa120\sb120\qr\f1\fs16 </xsl:text>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="image">
+ <xsl:text>\{bmct </xsl:text>
+ <xsl:value-of select="@source"/>
+ <xsl:text>\}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="newsfor">
+ <xsl:text>&#xA;\par\pard\plain\f1\fs24\qc\cf2\b </xsl:text>
+ <xsl:value-of select="@version"/>
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="@date"/>
+ <xsl:apply-templates/>
+ </xsl:template>
+ <xsl:template match="ni">
+ <xsl:text>&#xA;\par\pard\plain\fi0\li0\f1\fs18 \bullet </xsl:text>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="b">
+ <xsl:text>{\b </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+ <xsl:template match="i">
+ <xsl:text>{\i </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+ <xsl:template match="u">
+ <xsl:text>{\ul </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+ <xsl:template match="strike">
+ <xsl:text>{\strike </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="kin">
+ <xsl:choose>
+ <xsl:when test="@href">
+ <xsl:call-template name="hyperref">
+ <xsl:with-param name="href" select="@href"/>
+ <xsl:with-param name="inset"><xsl:text>{\b </xsl:text><xsl:apply-templates/><xsl:text>}</xsl:text></xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>{\b </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="product">
+ <xsl:choose>
+ <xsl:when test="@href">
+ <xsl:call-template name="hyperref">
+ <xsl:with-param name="href" select="@href"/>
+ <xsl:with-param name="inset"><xsl:text>{\b\cf6 </xsl:text><xsl:apply-templates/><xsl:text>}</xsl:text></xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>{\b\cf6 </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="term">
+ <xsl:text>{\i </xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="rfc">
+ <xsl:call-template name="hyperref">
+ <xsl:with-param name="href" select="concat('http://www.rfc-editor.org/rfc/rfc',@num,'.txt')"/>
+ <xsl:with-param name="inset" select="concat('{\b RFC',@num,'}')"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="license">
+ <xsl:text>&#xA;{</xsl:text>
+ <xsl:text>&#xA;\par\pard\plain\sb360\sa120 \f1\fs16 Copyright (c) </xsl:text>
+ <xsl:value-of select="@years"/>
+ <xsl:text> {\uldb\cf0 Klever Group (http://www.klever.net/)}{\v %!ExecFile("http://www.klever.net/")}</xsl:text>
+ <xsl:text>&#xA;\par\qj\sb120\sa120</xsl:text>
+ <xsl:text>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</xsl:text>
+ <xsl:text>&#xA;\par The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</xsl:text>
+ <xsl:text>&#xA;\par \sa360 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</xsl:text>
+ <xsl:text>&#xA;}</xsl:text>
+ </xsl:template>
+ <xsl:template match="credits">
+ <xsl:text>&#xA;\par \sa0\sb120\ql \f1\fs16 Author: {\b\uldb\cf11 Michael Krelin ({\i hacker@klever.net})}{\v %!ExecFile("mailto:hacker@klever.net")}</xsl:text>
+ <xsl:text>&#xA;\par \sa0\sb0 Fan mail send to {\i\uldb gefilte@klever.net}{\v %!ExecFile("mailto:gefilte@klever.net")}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="ul">
+ <xsl:text>\pard</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>\pard</xsl:text>
+ </xsl:template>
+ <xsl:template match="li">
+ <!-- TODO: could be done better, but you never know with winhelp.. -->
+ <xsl:variable name="li" select=" count(ancestor::ul) "/>
+ <xsl:text>&#xA;\par \fi0\li</xsl:text><xsl:value-of
+ select="0"/><xsl:text> \bullet </xsl:text>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="topic/text()">
+ <!-- maybe only omit spaces? -->
+ </xsl:template>
+ <xsl:template match="ul/text()">
+ </xsl:template>
+
+ <xsl:template name="colortbl">
+ <xsl:text>{\colortbl;
+ \red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;
+ \red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;
+ \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;
+ \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
+ </xsl:text>
+ </xsl:template>
+ <xsl:template name="fonttbl">
+ <xsl:text>{\fonttbl</xsl:text>
+ <xsl:text>{\f0\froman Times New Roman;}</xsl:text>
+ <xsl:text>{\f1\fswiss Arial;}</xsl:text>
+ <xsl:text>{\f3\froman Symbol;}</xsl:text>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/shared-code/ms_icmp.h b/shared-code/ms_icmp.h
new file mode 100644
index 0000000..32d97f5
--- a/dev/null
+++ b/shared-code/ms_icmp.h
@@ -0,0 +1,77 @@
+/*------------------------------------------------------------------
+* Filename: MS_ICMP.H
+*
+* Description: Prototypes of Microsoft's ICMP.DLL functions for
+* access to Internet Control Message Protocol (their stacks do
+* not support the standard Berkeley Sockets raw socket API).
+* Use this to do "ping" or "traceroute," although beware that
+* Microsoft discourages its use.
+*/
+
+
+/* Note 2: For the most part, you can refer to RFC 791 for detials on
+* how to fill in values for the IP option information structure. */
+typedef struct ip_option_information {
+ u_char Ttl; /* Time To Live (used for traceroute) */
+ u_char Tos; /* Type Of Service (usually 0) */
+ u_char Flags; /* IP header flags (usually 0) */
+ u_char OptionsSize; /* Size of options data (usually 0, max 40) */
+ u_char FAR *OptionsData;/* Options data buffer */
+} IPINFO, *PIPINFO, FAR *LPIPINFO;
+
+/* Note 1: The Reply Buffer will have an array of ICMP_ECHO_REPLY
+* structures, followed by options and the data in ICMP echo reply
+* datagram received. You must have room for at least one ICMP
+* echo reply structure, plus 8 bytes for an ICMP header. */
+typedef struct icmp_echo_reply {
+ u_long Address; /* source address */
+ u_long Status; /* IP status value (see below) */
+ u_long RTTime; /* Round Trip Time in milliseconds */
+ u_short DataSize; /* reply data size */
+ u_short Reserved; /* */
+ void FAR *Data; /* reply data buffer */
+ typedef struct ip_option_information Options; /* reply options */
+} ICMPECHO, *PICMPECHO, FAR *LPICMPECHO;
+
+#define IP_STATUS_BASE 11000
+#define IP_SUCCESS 0
+#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
+#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
+#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
+#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
+#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
+#define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
+#define IP_BAD_OPTION (IP_STATUS_BASE + 7)
+#define IP_HW_ERROR (IP_STATUS_BASE + 8)
+#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
+#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
+#define IP_BAD_REQ (IP_STATUS_BASE + 11)
+#define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
+#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
+#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
+#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
+#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
+#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
+#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
+#define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
+#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
+#define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
+#define IP_UNLOAD (IP_STATUS_BASE + 22)
+#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
+#define MAX_IP_STATUS IP_GENERAL_FAILURE
+#define IP_PENDING (IP_STATUS_BASE + 255)
+
+
+HANDLE WINAPI PASCAL IcmpCreateFile(VOID); /* INVALID_HANDLE_VALUE on error */
+BOOL WINAPI PASCAL IcmpCloseHandle(HANDLE IcmpHandle); /* FALSE on error */
+DWORD WINAPI PASCAL IcmpSendEcho(
+ HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
+ u_long DestAddress, /* destination IP address (in network order) */
+ LPVOID RequestData, /* pointer to buffer to send */
+ WORD RequestSize, /* length of data in buffer */
+ LPIPINFO RequestOptns, /* see Note 2 below */
+ LPVOID ReplyBuffer, /* see Note 1 below */
+ DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
+ DWORD Timeout /* time in milliseconds to wait for reply */
+);
+
diff --git a/shared-data/browse-icon.ico b/shared-data/browse-icon.ico
new file mode 100644
index 0000000..d2d1b3c
--- a/dev/null
+++ b/shared-data/browse-icon.ico
Binary files differ
diff --git a/shared-data/install-icon.ico b/shared-data/install-icon.ico
new file mode 100644
index 0000000..23e86a6
--- a/dev/null
+++ b/shared-data/install-icon.ico
Binary files differ
diff --git a/shared-data/klever-background.bmp b/shared-data/klever-background.bmp
new file mode 100644
index 0000000..e4d87ec
--- a/dev/null
+++ b/shared-data/klever-background.bmp
Binary files differ
diff --git a/shared-data/play-icon.ico b/shared-data/play-icon.ico
new file mode 100644
index 0000000..3d2a11e
--- a/dev/null
+++ b/shared-data/play-icon.ico
Binary files differ
diff --git a/stdafx.cpp b/stdafx.cpp
new file mode 100644
index 0000000..560a1b0
--- a/dev/null
+++ b/stdafx.cpp
@@ -0,0 +1,6 @@
+// stdafx.cpp : source file that includes just the standard includes
+// T42.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/stdafx.h b/stdafx.h
new file mode 100644
index 0000000..6c6a53e
--- a/dev/null
+++ b/stdafx.h
@@ -0,0 +1,70 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxrich.h>
+#include <afxtempl.h>
+
+#include <afxsock.h> // MFC socket extensions
+
+#pragma warning(disable: 4786)
+
+#include "shared-code/FindIFace.h"
+#include "shared-code/kHelpers.h"
+#include "shared-code/BTreendex.h"
+#include "shared-code/BitSet.h"
+
+#define REFS2PTS 16
+
+struct osockaddr {
+ u_short sa_family; // Address family
+ char sa_data[14];// Up to 14 bytes of direct address
+
+ osockaddr& operator=(sockaddr_in& src) { Copy(src); return *this; }
+ void Copy(sockaddr_in& src) {
+ sa_family = htons(src.sin_family);
+ memmove(sa_data,((sockaddr*)&src)->sa_data,sizeof(((sockaddr*)&src)->sa_data));
+ }
+};
+
+#include "talkd.h"
+
+#include "T42CallLog.h"
+
+enum {
+ WM_INITIATETALK = WM_USER+16,
+ WM_TARGETRESOLVED,
+ WM_SOURCERESOLVED,
+ WM_LOOKUP_SUCCESS, WM_LOOKUP_FAILURE,
+ WM_ANNOUNCE_SUCCESS, WM_ANNOUNCE_FAILURE,
+ WM_LEAVEINVITE_SUCCESS, WM_LEAVEINVITE_FAILURE,
+ WM_LOCAL_REMOVE_SUCCESS, WM_LOCAL_REMOVE_FAILURE,
+ WM_REMOTE_REMOVE_SUCCESS, WM_REMOTE_REMOVE_FAILURE,
+ WM_TALKACCEPT,
+ WM_CTLTRANSACT,
+ WM_TALK,
+ WM_TALKCHAR,
+ WM_SPLITTERBDOWN,
+ WM_TALKCONNECT,
+ WM_NAMERESOLVED, WM_IPRESOLVED,
+
+ WM_TRAYICON,
+ WM_DAEMON,
+ WM_UPDATEPREVIEW,
+
+ timerTransact = 1,
+ timerTimeout,
+ timerMinutes
+};
+#include <MMSystem.h>
+// CG: The following line was added by the Windows Multimedia component.
+#pragma comment(lib, "winmm.lib")
diff --git a/talkd.h b/talkd.h
new file mode 100644
index 0000000..2deb124
--- a/dev/null
+++ b/talkd.h
@@ -0,0 +1,47 @@
+
+// Client->Server request message
+struct TalkCtlMessage {
+ u_char m_Version; // Protocol Version
+ u_char m_Type; // Request type
+ u_char m_Answer; // Unused
+ u_char m_Pad;
+ u_long m_ID; // Request ID
+ osockaddr m_Addr;
+ osockaddr m_ctlAddr;
+ long m_PID; // Caller's process id
+ char m_LName[12];// Caller's name (local)
+ char m_RName[12];// Callee's name (remote)
+ char m_RTTY[16]; // Callee's tty name
+
+};
+
+// Server->Client response message
+struct TalkCtlResponse {
+ u_char m_Version; // Protocol Version
+ u_char m_Type; // Request type
+ u_char m_Answer; // Response itself
+ u_char m_Pad;
+ u_long m_ID; // Request ID
+ osockaddr m_Addr; // Adress for establishing communication
+};
+
+enum {
+ talkCtlVersion = 1,
+ // Message Types
+ talkCtlReqLeaveInvite = 0, // Leave an invitation with server
+ talkCtlReqLookUp = 1, // Check for invitation by callee
+ talkCtlReqDelete = 2, // Delete invitation by caller
+ talkCtlReqAnnounce = 3, // Announce invitation by caller
+ // Answers
+ talkCtlSuccess = 0, // Operation completed properly
+ talkCtlNotHere = 1, // Callee not logged in
+ talkCtlFailed = 2, // Failed for unexplained reason
+ talkCtlMachineUnknown = 3, // Caller's machine name unknown
+ talkCtlPermissionDenied = 4, // Callee's tty doesn't permit announce
+ talkCtlUnknownRequest = 5, // Request has invalid type
+ talkCtlBadVersion = 6, // Request has invalid protocol version
+ talkCtlBadAddr = 7, // Request has invalid addr value
+ talkCtlBadCtlAddr = 8, // Request has invalid ctlAddr value
+
+ talkCtlReserved = 255 // Internal use
+}; \ No newline at end of file