summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2004-07-05 01:53:09 (UTC)
committer Michael Krelin <hacker@klever.net>2004-07-05 01:53:09 (UTC)
commit885f8cc426a8840ae61023b75f3f0e4a1e268082 (patch) (unidiff)
tree5e942d450c97ca0bf0f9cfb80aa0fefb486535d9
downloadkinsole-885f8cc426a8840ae61023b75f3f0e4a1e268082.zip
kinsole-885f8cc426a8840ae61023b75f3f0e4a1e268082.tar.gz
kinsole-885f8cc426a8840ae61023b75f3f0e4a1e268082.tar.bz2
initial commit into svn repository
git-svn-id: http://svn.klever.net/kin/kinsole/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore26
-rw-r--r--COPYING19
-rw-r--r--KTAGS12
-rw-r--r--NAWS.cpp18
-rw-r--r--NEW-ENVIRON.cpp272
-rw-r--r--README27
-rw-r--r--TIMING-MARK.cpp22
-rw-r--r--TTY.cpp45
-rw-r--r--VT100.cpp1478
-rw-r--r--help/kinsole.cnt9
-rw-r--r--help/kinsole.hpj17
-rw-r--r--help/kinsole.rtf97
-rw-r--r--help/kinsole.xml72
-rw-r--r--install/custom.rch3
-rw-r--r--install/install.cpp65
-rw-r--r--install/install.rc182
-rw-r--r--install/resource.h24
-rw-r--r--kinsole.cpp736
-rw-r--r--kinsole.mak612
-rw-r--r--kinsole.rc115
-rw-r--r--makehelp.bat11
-rw-r--r--options.cpp371
-rw-r--r--res/kinsole.icobin0 -> 4710 bytes
-rw-r--r--resource.h16
-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--status.cpp30
-rw-r--r--terminal.cpp147
48 files changed, 9894 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b2ee9ee
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
1
2# /
3/Debug
4/Release
5/debug
6/release
7/releast
8/DEBUG
9/RELEASE
10/*.mdp
11/*.ncb
12/*.aps
13
14# /help/
15/help/KINSOLE.HLP
16/help/kinsole.LOG
17/help/kinsole.GID
18
19# /install/
20/install/debug
21/install/release
22/install/Debug
23/install/Release
24/install/DEBUG
25/install/RELEASE
26/install/*.aps
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..997e508
--- a/dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
1Copyright (c) 1998, 2002 Klever Group (http://www.klever.net/)
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/KTAGS b/KTAGS
new file mode 100644
index 0000000..dfc79bb
--- a/dev/null
+++ b/KTAGS
@@ -0,0 +1,12 @@
1 help-license-date ./help/kinsole.xml /<license\s/;"kind:d
2 help-news ./help/kinsole.xml/<newsfor\s/
3 install-version ./install/install.cpp /^#define\s\+KINAME\s\+"/;"kind:v
4 install-vsinfo-date install/install.rc /^\s\+VALUE\s\+"LegalCopyright",/;"kind:d
5 install-vsinfo-numeric-version install/install.rc /^\s\+FILEVERSION\s\+/;"kind:v
6 install-vsinfo-string-version install/install.rc /^\s\+VALUE\s\+"FileVersion",/;"kind:v
7 kinsole-version kinsole.cpp /^#define\s\+DAMN_KIN_VERSION\s\+"/;"kind:v
8 license-date COPYING :1;"kind:d
9 usage-date kinsole.cpp /, Copyright (c) /;"kind:d
10 vsinfo-date kinsole.rc /VALUE\s\+"LegalCopyright",/;"kind:d
11 vsinfo-numeric-version kinsole.rc /^\s\+FILEVERSION\s\+/;"kind:v
12 vsinfo-string-version kinsole.rc /^\s\+VALUE\s\+"FileVersion",/;"kind:v
diff --git a/NAWS.cpp b/NAWS.cpp
new file mode 100644
index 0000000..c35f508
--- a/dev/null
+++ b/NAWS.cpp
@@ -0,0 +1,18 @@
1BOOL SendNAWS()
2{
3CONSOLE_SCREEN_BUFFER_INFO csbi;
4 VERIFY(::GetConsoleScreenBufferInfo(hConsoleOutput,&csbi));
5BYTE sbd[4];
6 sbd[0]=csbi.dwSize.X>>8;
7 sbd[1]=csbi.dwSize.X&0xFF;
8 sbd[2]=csbi.dwSize.Y>>8;
9 sbd[3]=csbi.dwSize.Y&0xFF;
10 return SubNegotiate(toNAWS,sbd,sizeof(sbd));
11}
12
13BOOL nawsOnDo()
14{
15 TRACE0("DO NAWS\n");
16 AskWill(toNAWS);
17 return SendNAWS();
18}
diff --git a/NEW-ENVIRON.cpp b/NEW-ENVIRON.cpp
new file mode 100644
index 0000000..370ff73
--- a/dev/null
+++ b/NEW-ENVIRON.cpp
@@ -0,0 +1,272 @@
1
2 enum_NESB {
3 nesbSend = 1,
4 nesbIs = 0,
5 nesbInfo = 2,
6
7 nesbVar = 0,
8 nesbValue = 1,
9 nesbESC = 2,
10 nesbUserVar = 3,
11
12 nesbNothing = 256
13};
14
15 struct _envariable{
16 BYTEtype;
17 char*name;
18 char*value;
19 _envariable() : type(0), name(NULL), value(NULL) {}
20 ~_envariable() { ItIsNot(); }
21 void ItIsNot() {
22 if(name) delete name;
23 if(value) delete value;
24 }
25 BOOL ItIs(BYTE t,LPCTSTR n,LPCTSTR v) {
26 ItIsNot();
27 name = new CHAR[strlen(n)+1]; strcpy(name,n);
28 value = new CHAR[strlen(v)+1]; strcpy(value,v);
29 type=t;
30 return TRUE;
31 }
32 intTransmitSize() {
33 char* v = value;
34 for(int rv=0;*v;v++,rv++){
35 switch(*v){
36 case nesbVar:
37 case nesbValue:
38 case nesbUserVar:
39 case nesbESC:
40 rv++;
41 break;
42 }
43 }
44 for(v=name;*v;v++,rv++){
45 switch(*v){
46 case nesbVar:
47 case nesbValue:
48 case nesbUserVar:
49 case nesbESC:
50 rv++;
51 break;
52 }
53 }
54 return rv+2;// VAR/VAL
55 }
56 int Paste(CHAR* data) {
57 int rv=0;
58 ASSERT(type==nesbVar || type==nesbUserVar);
59 data[rv++]=type;
60 for(CHAR* v=name;*v;v++){
61 switch(*v){
62 case nesbVar:
63 case nesbValue:
64 case nesbUserVar:
65 case nesbESC:
66 data[rv++]=nesbESC;
67 default:
68 data[rv++]=*v;
69 }
70 }
71 data[rv++]=nesbValue;
72 for(v=value;*v;v++){
73 switch(*v){
74 case nesbVar:
75 case nesbValue:
76 case nesbUserVar:
77 case nesbESC:
78 data[rv++]=nesbESC;
79 default:
80 data[rv++]=*v;
81 }
82 }
83 return rv;
84 }
85 BOOL IsIt(CHAR* n,int l) {
86 BOOL bESC = FALSE;
87 CHAR* nPtr = name;
88 for(int tmp=0;tmp<l;tmp++){
89 if(!*nPtr)
90 return FALSE;
91 if(bESC)
92 bESC=FALSE;
93 else if(n[tmp]==nesbESC)
94 bESC=TRUE;
95 else if(n[tmp]!=*(nPtr++))
96 return FALSE;
97 }
98 return (*nPtr)?FALSE:TRUE;
99 }
100 }*Envars = NULL;
101 intnEnvars = 0;
102int nEnvarsAllocated = 0;
103
104_envariable* FindEnvar(BYTE type,CHAR* n,int l)
105{
106 ASSERT(Envars && nEnvars);
107 for(int tmp=0;tmp<nEnvars;tmp++){
108 if(Envars[tmp].type!=type)
109 continue;
110 if(Envars[tmp].IsIt(n,l))
111 return &Envars[tmp];
112 }
113 return NULL;
114}
115
116 #define ENVGROW8
117
118BOOL AddEnvar(BYTE type,LPTSTR name,LPTSTR value)
119{
120 if(Envars && nEnvars){
121 if(FindEnvar(type,name,strlen(name)))// ** Maybe replace
122 return FALSE;
123 }
124 if(nEnvars>=nEnvarsAllocated){
125 ASSERT(nEnvars==nEnvarsAllocated);
126 _envariable* ne = new _envariable[nEnvarsAllocated+ENVGROW];
127 ASSERT(ne);
128 if(nEnvarsAllocated){
129 memmove(ne,Envars,sizeof(_envariable)*nEnvarsAllocated);
130 delete Envars;
131 }
132 Envars=ne;
133 nEnvarsAllocated+=ENVGROW;
134 }
135 return Envars[nEnvars++].ItIs(type,name,value);
136}
137BOOL CleanEnvars()
138{
139 if(Envars){
140 ASSERT(nEnvarsAllocated);
141 delete[] Envars;
142 }
143 return TRUE;
144}
145
146BOOL newenvironOnDont()
147{
148 TRACE0("DONT NEW-ENVIRON\n");
149 return TRUE;
150}
151BOOL newenvironOnDo()
152{
153 TRACE0("DO NEW-ENVIRON\n");
154 return (Envars && nEnvars)?TRUE:FALSE;
155}
156BOOL newenvironOnSB(LPBYTE data,UINT size)
157{
158 if(!size)
159 return FALSE;
160 if(data[0]!=nesbSend)
161 return FALSE;
162 if(!(Envars && nEnvars)){
163 BYTE no = nesbIs;
164 return SubNegotiate(toNewEnviron,&no,1);
165 }
166 UINT totalSize = 1;// IS byte
167 if(size>1 ){
168 int type = 0;
169 int name = 0;
170 BOOL bESC = FALSE;
171 for(UINT tmp=1;tmp<=size;tmp++){
172 switch((tmp==size)?nesbNothing:(UINT)data[tmp]){
173 case nesbESC:
174 bESC=TRUE;
175 break;
176 case nesbVar:
177 case nesbUserVar:
178 case nesbNothing:
179 if(!bESC){
180 if(type){
181 if(name){
182 _envariable* ev = FindEnvar(data[type],(CHAR*)&data[name],tmp-name);
183 if(ev){
184 totalSize+=ev->TransmitSize();
185 }
186 }else{
187 for(int tmp=0;tmp<nEnvars;tmp++){
188 if(Envars[tmp].type==data[type]){
189 totalSize+=Envars[tmp].TransmitSize();
190 }
191 }
192 }
193 type=tmp;
194 name=0;
195 }else{
196 type=tmp;
197 ASSERT(!name);
198 }
199 break;
200 }
201 // Fall through if ESCaped
202 default:
203 bESC=FALSE;
204 if(!name)
205 name=tmp;
206 break;
207 }
208 }
209 TRACE1("Total Size: %u\n",totalSize);
210 CHAR* d = new CHAR[totalSize];
211 UINT ptr = 0;
212 d[ptr++]=nesbIs;
213 for(tmp=1;tmp<=size;tmp++){
214 switch((tmp==size)?nesbNothing:(UINT)data[tmp]){
215 case nesbESC:
216 bESC=TRUE;
217 break;
218 case nesbVar:
219 case nesbUserVar:
220 case nesbNothing:
221 if(!bESC){
222 if(type){
223 if(name){
224 _envariable* ev = FindEnvar(data[type],(CHAR*)&data[name],tmp-name);
225 if(ev){
226 ptr+=ev->Paste(&d[ptr]);
227 }
228 }else{
229 for(int tmp=0;tmp<nEnvars;tmp++){
230 if(Envars[tmp].type==data[type]){
231 ptr+=Envars[tmp].Paste(&d[ptr]);
232 }
233 }
234 }
235 ASSERT(ptr<=totalSize);
236 type=tmp;
237 name=0;
238 }else{
239 type=tmp;
240 ASSERT(!name);
241 }
242 break;
243 }
244 // Fall through if ESCaped
245 default:
246 bESC=FALSE;
247 if(!name)
248 name=tmp;
249 break;
250 }
251 }
252 ASSERT(ptr==totalSize);
253 VERIFY(SubNegotiate(toNewEnviron,(BYTE*)d,totalSize));
254 delete d;
255 }else{
256 for(int tmp=0;tmp<nEnvars;tmp++){
257 totalSize+=Envars[tmp].TransmitSize();
258 }
259 TRACE1("Total Size: %u\n",totalSize);
260 CHAR* d = new CHAR[totalSize];
261 UINT ptr = 0;
262 d[ptr++]=nesbIs;
263 for(tmp=0;tmp<nEnvars;tmp++){
264 ptr+=Envars[tmp].Paste(&d[ptr]);
265 ASSERT(ptr<=totalSize);
266 }
267 ASSERT(ptr==totalSize);
268 VERIFY(SubNegotiate(toNewEnviron,(BYTE*)d,totalSize));
269 delete d;
270 }
271 return TRUE;
272} \ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..9bbcbe8
--- a/dev/null
+++ b/README
@@ -0,0 +1,27 @@
1
2Release checklist:
3 (These are tags stored in KTAGS file. please, keep in sync. Use vim to
4 jump to these tags. I haven't tried it on windows, though).
5
6 |help-news| - Release notes in help file
7
8Version number in the following places:
9
10 |kinsole-version| - KINSole code define
11 |vsinfo-numeric-version| - VERSIONINFO numerical File&Prod V
12 |vsinfo-string-version| - VERSIONINFO string File&Prod V
13 |install-version| - Version used in install
14 |install-vsinfo-numeric-version|- install's VERSIONINFO block
15 |install-vsinfo-string-version| - install's VERSIONINFO block
16
17If the year flips check these:
18
19 |usage-date| - Usage message copyright notice
20 |help-license-date| - license in help file
21 |license-date| - license in COPYING file
22 |vsinfo-date| - Copyright in VERSIONINFO block
23 |install-vsinfo-date| - Copyright in install's VERSIONINFO
24
25
26This is for vim (don't remove):
27 vim:set tags=KTAGS isk=!-~,^*,^\|,^\" ft=help:
diff --git a/TIMING-MARK.cpp b/TIMING-MARK.cpp
new file mode 100644
index 0000000..3f4c24b
--- a/dev/null
+++ b/TIMING-MARK.cpp
@@ -0,0 +1,22 @@
1BOOL tmOnDo()
2{
3 ShowWill(toTimingMark);
4 Options[toTimingMark].m_StateU=TOption::stateWantNo;
5 return FALSE;
6}
7
8BOOL tmOnWill()
9{
10 //
11 if(hConsoleWindow){
12 for(int tmp=0;tmp<3;tmp++){
13 FlashWindow(hConsoleWindow,TRUE);
14 Sleep(300);
15 FlashWindow(hConsoleWindow,FALSE);
16 Sleep(300);
17 }
18 }else
19 Beep(880,100);
20 Options[toTimingMark].m_StateH=TOption::stateWantNo;
21 return FALSE;
22}
diff --git a/TTY.cpp b/TTY.cpp
new file mode 100644
index 0000000..6d4cc73
--- a/dev/null
+++ b/TTY.cpp
@@ -0,0 +1,45 @@
1 class CTTY{
2public:
3 virtual BOOL Input(UINT c) {
4 VERIFY(SendLiteral(c));
5 if(
6 (
7 Options[toEcho].m_StateU==TOption::stateYes
8 || Options[toEcho].m_StateU==TOption::stateNone
9 ) && (
10 Options[toEcho].m_StateH!=TOption::stateYes
11 || Options[toEcho].m_StateH==TOption::stateNone
12 )
13 ){
14 PreOutput();
15 Output(c);
16 PostOutput();
17 }
18 return TRUE;
19 }
20 virtual BOOL VInput(WORD vk,DWORD cks) {
21 return TRUE;
22 }
23 virtualBOOL PreOutput() {
24 return TRUE;
25 }
26 virtual BOOL Output(UINT c) {
27 if(!c)
28 return TRUE;
29 static DWORD dummyWritten = 0;
30 VERIFY(::WriteConsole(hConsoleOutput,&c,1,&dummyWritten,NULL));
31 return TRUE;
32 }
33 virtual BOOL PostOutput() {
34 return TRUE;
35 }
36 virtual BOOL Init() {
37 return TRUE;
38 }
39 virtual LPCTSTR GetTitle() {
40 if(TTTermType<0)
41 return "Unknown Terminal Type";
42 return TTypes[TTTermType].m_Name;
43 }
44}
45 TT_TTY; \ No newline at end of file
diff --git a/VT100.cpp b/VT100.cpp
new file mode 100644
index 0000000..ea626a9
--- a/dev/null
+++ b/VT100.cpp
@@ -0,0 +1,1478 @@
1 class CVT100 : public CTTY{
2 static DWORDdummyWritten;
3 static CHARm_ctGraphs[256];
4 CHARsfCrap[256];
5public:
6 BYTE m_Sequence[1024]; // Buffered ESC[ sequence
7 UINT m_Sequenced;
8 CHAR_INFO m_Buffer[132*2];// Deferred output buffer
9 UINT m_Buffered;
10 UINT m_Parms[16]; // ESC[ Parameters
11 UINT m_nParms;
12 UINT m_ParmPtrs[16];
13 INT m_TABs[132]; // Tabulations
14 CHAR* m_CT; // Codes table for various charsets
15 CHAR* m_ctG0;
16 CHAR* m_ctG1;
17 int m_ctG;
18 CHAR* m_savedCTG0; // Saved for ESC#7/ESC#8
19 CHAR* m_savedCTG1;
20 CHAR* m_savedCT;
21 COORD m_savedCP;
22 int m_savedCTG;
23 int m_savedAttrs;
24 BOOL m_bRight; // At right margin
25 BOOL m_bKPN; // Keypad is in numeric mode
26 BOOL m_bCKM; // Cursor Keys Mode (DECCKM)
27 BOOL m_bAWM; // Autowrap mode
28 BOOL m_bOM; // Origin Mode
29 BOOL m_bLNM; // New Line Mode
30 BOOL m_bIM; // Insert Mode
31 BOOL m_bVT52; // VT52 Mode (as opposed to ANSI which is default)
32 BOOL m_bTR; // Total Reverse of the whole screen background/foreground
33 BOOL m_bEBFailure; // ESC[ Failure flag
34 int m_vt52Y1, m_vt52Y2; // ESCY in VT52 mode parameters
35
36 CHAR_INFO* m_tmpScrollBuffer;// Buffer used for temporary storage when doing scrolling.
37 UINT m_tmpScrollBufferSize;
38
39 void AllocateTmpBuffer() {
40 UINT newSize = m_CSBI.dwSize.X*m_CSBI.dwSize.Y;
41 if(newSize>m_tmpScrollBufferSize || !m_tmpScrollBuffer){
42 if(m_tmpScrollBuffer) delete m_tmpScrollBuffer;
43 VERIFY(m_tmpScrollBuffer=new CHAR_INFO[newSize]);
44 m_tmpScrollBufferSize=newSize;
45 }
46 }
47
48 CVT100() : m_tmpScrollBuffer(NULL) { }
49 virtual ~CVT100() { if(m_tmpScrollBuffer) delete m_tmpScrollBuffer; }
50
51 enum _state {
52 stateNone,stateESeq,stateEBSeq, stateEPOSeq, stateEPCSeq, stateEPSSeq,
53 stateEY52Seq1, stateEY52Seq2
54 }state;
55
56 enum _attrs {
57 attrNone = 0, attrBold = 1, attrUnderline = 2, attrBlink = 4, attrReverse = 8
58 };
59 int attrs; // Screen attributes from _attrs enumeration
60 int sr0,sr1; // Scroll Region
61 int m_Attrs; // Screen attributes in console terms
62 int m_bgAttr; // Background color
63 int m_fgAttr; // Foreground color
64
65 CONSOLE_SCREEN_BUFFER_INFO
66 m_CSBI; // Tracking of SB information
67
68 void FillScreen(int x,int y,int n,TCHAR c,WORD a) {
69 COORD tmp = {x,y};
70 VERIFY(FillConsoleOutputCharacter(hConsoleOutput,c,n,tmp,&dummyWritten));
71 VERIFY(FillConsoleOutputAttribute(hConsoleOutput,a,n,tmp,&dummyWritten));
72 }
73 void HScroll(int x,int y,int n,int x1=-1) {
74 if(!n)
75 return;
76 if(x1<0)
77 x1=m_CSBI.dwSize.X-1;
78 else
79 x1=max(x,min(x1,m_CSBI.dwSize.X-1));
80 static
81 COORD zero = {0,0};
82 if(n>0){
83 int r = max(0,min(n,x1-x+1));
84 if(!r)
85 return;
86 if((x+r)<=x1){
87 ASSERT(m_tmpScrollBuffer);
88 SMALL_RECT sr = { x,y,x1-r,y };
89 VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
90 sr.Left+=r;
91 sr.Right+=r;
92 VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
93 }
94 FillScreen(x,y,r,' ',m_Attrs);
95 }else{
96 int r = max(0,min(-n,x1-x+1));
97 if(!r)
98 return;
99 if((x+r)<=x1){
100 ASSERT(m_tmpScrollBuffer);
101 SMALL_RECT sr = {x+r,y,x1,y };
102 VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
103 sr.Left-=r;
104 sr.Right-=r;
105 VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
106 }
107 FillScreen(x1-r+1,y,r,' ',m_Attrs);
108 }
109 }
110
111 void VScroll(int y,int n,int y1=-1) {
112 static
113 COORD zero = {0,0};
114 if(!n)
115 return;
116 if(y1<0)
117 y1 = m_CSBI.dwSize.Y;
118 else
119 y1 = max(y,min(y1,m_CSBI.dwSize.Y-1));
120 if(n>0){
121 int r = max(0,min(n,y1-y+1));
122 if(!r)
123 return;
124 if((y+r)<=y1){
125 ASSERT(m_tmpScrollBuffer);
126 SMALL_RECT sr = { 0,y,m_CSBI.dwSize.X-1,y1-r };
127 VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
128 sr.Top+=r;
129 sr.Bottom+=r;
130 VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
131 }
132 FillScreen(0,y,r*m_CSBI.dwSize.X,' ',m_Attrs);
133 }else{
134 int r = max(0,min(-n,y1-y+1));
135 if(!r)
136 return;
137 if((y+r)<=y1){
138 ASSERT(m_tmpScrollBuffer);
139 SMALL_RECT sr = {0,y+r,m_CSBI.dwSize.X-1,y1 };
140 VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
141 sr.Top-=r;
142 sr.Bottom-=r;
143 VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&sr));
144 }
145 FillScreen(0,y1-r+1,r*m_CSBI.dwSize.X,' ',m_Attrs);
146 }
147 }
148
149 BOOL DoNAWS() {
150 VERIFY(GetConsoleScreenBufferInfo(hConsoleOutput,&m_CSBI));
151 AllocateTmpBuffer();
152 VERIFY(TerminalUpdateTitle());
153 if(Options[toNAWS].m_StateU==TOption::stateYes)
154 SendNAWS();
155 else
156 AskWill(toNAWS);
157 return TRUE;
158 }
159
160 BOOL ResizeWindow(COORD ns) {
161 if(m_CSBI.dwCursorPosition.X>=ns.X)
162 m_CSBI.dwCursorPosition.X=0;
163 if(m_CSBI.dwCursorPosition.Y>=ns.Y){
164 VScroll(0,-(m_CSBI.dwCursorPosition.Y-ns.Y+1),m_CSBI.dwCursorPosition.Y);
165 m_CSBI.dwCursorPosition.Y=ns.Y-1;
166 }
167 if(!SetConsoleCursorPosition(hConsoleOutput,m_CSBI.dwCursorPosition))
168 return FALSE;
169 if(ns.X<m_CSBI.dwSize.X || ns.Y<m_CSBI.dwSize.Y){
170 SMALL_RECT wi = { 0,0,min(ns.X-1,m_CSBI.dwMaximumWindowSize.X-1),
171 min(ns.Y-1,m_CSBI.dwMaximumWindowSize.Y-1)
172 };
173 if(!SetConsoleWindowInfo(hConsoleOutput,TRUE,&wi))
174 return FALSE;
175 }
176 if(!SetConsoleScreenBufferSize(hConsoleOutput,ns))
177 TRACE2("Failed to set buffer size to %dx%d\n",ns.X,ns.Y);
178 else{
179 DoNAWS();
180 if(sr0>=m_CSBI.dwSize.Y){
181 sr0=0; sr1=m_CSBI.dwSize.Y-1;
182 }else if(sr1>=m_CSBI.dwSize.Y){
183 sr1=m_CSBI.dwSize.Y-1;
184 if(sr0>=sr1)
185 sr0=0;
186 }
187 }
188 return TRUE;
189 }
190
191 WORD ReverseAttribute(WORD a) {
192 WORD rv = 0;
193 if(a&FOREGROUND_RED)
194 rv|=BACKGROUND_RED;
195 if(a&FOREGROUND_GREEN)
196 rv|=BACKGROUND_GREEN;
197 if(a&FOREGROUND_BLUE)
198 rv|=BACKGROUND_BLUE;
199 if(a&FOREGROUND_INTENSITY)
200 rv|=BACKGROUND_INTENSITY;
201 if(a&BACKGROUND_RED)
202 rv|=FOREGROUND_RED;
203 if(a&BACKGROUND_GREEN)
204 rv|=FOREGROUND_GREEN;
205 if(a&BACKGROUND_BLUE)
206 rv|=FOREGROUND_BLUE;
207 if(a&BACKGROUND_INTENSITY)
208 rv|=FOREGROUND_INTENSITY;
209 return rv;
210 }
211
212 void ReverseScreen() {
213 static
214 COORD zero = {0,0};
215 SMALL_RECT whole = {0,0,m_CSBI.dwSize.X-1,m_CSBI.dwSize.Y-1};
216 ASSERT(m_tmpScrollBuffer);
217 VERIFY(ReadConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&whole));
218 for(int tmp=0;tmp<(m_CSBI.dwSize.X*m_CSBI.dwSize.Y);tmp++)
219 m_tmpScrollBuffer[tmp].Attributes = ReverseAttribute(m_tmpScrollBuffer[tmp].Attributes);
220 VERIFY(WriteConsoleOutput(hConsoleOutput,m_tmpScrollBuffer,m_CSBI.dwSize,zero,&whole));
221 }
222
223 BOOL SetAttrs() {
224 WORD a = (attrs&attrReverse)?BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE:
225 FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
226 if(m_fgAttr>=0){
227 a&=~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
228 a|=m_fgAttr|FOREGROUND_INTENSITY;
229 }
230 if(m_bgAttr>=0){
231 a&=~(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
232 a|=m_bgAttr;
233 }
234 if(attrs&attrBold)
235 a|=FOREGROUND_INTENSITY;
236 if((attrs&attrUnderline) && (m_fgAttr<0)){
237 if(attrs&attrReverse)// Is it right way to underline? - we make foreground blue.
238 a|=FOREGROUND_BLUE;
239 else
240 a&=~(FOREGROUND_RED|FOREGROUND_GREEN);
241 }
242 if(attrs&attrBlink)
243 a|=BACKGROUND_INTENSITY;
244 if(m_bTR)
245 m_Attrs=ReverseAttribute(a);
246 else
247 m_Attrs = a;
248 return TRUE;
249 }
250
251 virtual BOOL Input(UINT c) {
252 VERIFY(SendLiteral(c));
253 if(c=='\r' && m_bLNM)
254 VERIFY(SendLiteral('\n'));
255 if(
256 (
257 Options[toEcho].m_StateU==TOption::stateYes
258 || Options[toEcho].m_StateU==TOption::stateNone
259 ) && (
260 Options[toEcho].m_StateH!=TOption::stateYes
261 || Options[toEcho].m_StateH==TOption::stateNone
262 )
263 ){
264 PreOutput();
265 Output(c);
266 if(c=='\r' && m_bLNM)
267 Output('\n');
268 PostOutput();
269 }
270 return TRUE;
271 }
272 virtual BOOL VInput(WORD vk,DWORD cks) {
273 #define AROKEY(c,n)( \
274 m_bVT52 \
275 ? "\33" c \
276 :( \
277 (cks&ENHANCED_KEY) \
278 ? (m_bCKM?"\33O" c:"\33[" c) \
279 : (m_bKPN \
280 ?"\33O" n \
281 :(m_bCKM?"\33O" c:"\33[" c) \
282 ) \
283 ) \
284)
285#define FUNKEY(c,s) ( \
286 (cks&SHIFT_PRESSED) \
287 ?( \
288 m_bVT52 \
289 ? NULL \
290 : "\33" s \
291 ) \
292 :( \
293 m_bVT52 \
294 ? "\33" c \
295 : "\33O" c \
296 ) \
297)
298 if(cks&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)){
299 COORD ns = {m_CSBI.dwSize.X,m_CSBI.dwSize.Y};
300 switch(vk){
301 case VK_UP:
302 if(ns.Y<2)
303 return TRUE;
304 ns.Y--;
305 break;
306 case VK_DOWN:
307 ns.Y++;
308 break;
309 case VK_LEFT:
310 if(ns.X<2)
311 return TRUE;
312 ns.X--;
313 break;
314 case VK_RIGHT:
315 ns.X++;
316 break;
317 default:
318 return TRUE;
319 }
320 ResizeWindow(ns);
321 return TRUE;
322 }
323 switch(vk){
324 case VK_F1: return VIn(FUNKEY("P","[23~"));
325 case VK_F2: return VIn(FUNKEY("Q","[24~"));
326 case VK_F3: return VIn(FUNKEY("R","[25~"));
327 case VK_F4: return VIn(FUNKEY("S","[26~"));
328 case VK_F5: return VIn(FUNKEY("t","[28~"));
329 case VK_F6: return VIn(FUNKEY("u","[29~"));
330 case VK_F7: return VIn(FUNKEY("v","[31~"));
331 case VK_F8: return VIn(FUNKEY("l","[32~"));
332 case VK_F9: return VIn(FUNKEY("w","[33~"));
333 case VK_F10:return VIn(FUNKEY("x","[34~")); // terminfo says kf10 "y"
334 case VK_F11:return VIn("\33[23~");
335 case VK_F12:return VIn("\33[24~");
336 case VK_UP:
337 case VK_NUMPAD8:return VIn(AROKEY("A","x"));
338 case VK_DOWN:
339 case VK_NUMPAD2:return VIn(AROKEY("B","r"));
340 case VK_LEFT:
341 case VK_NUMPAD4:return VIn(AROKEY("D","t"));
342 case VK_RIGHT:
343 case VK_NUMPAD6:return VIn(AROKEY("C","v"));
344 case VK_HOME:
345 case VK_NUMPAD7:return VIn((cks&ENHANCED_KEY)
346 ? (NULL)
347 : (m_bKPN?"\33Ow":"\33[1~")
348 );
349 case VK_END:
350 case VK_NUMPAD1:return VIn((cks&ENHANCED_KEY)
351 ? (NULL)
352 : (m_bKPN?"\33Oq":"\33[4~")
353 );
354 case VK_PRIOR:
355 case VK_NUMPAD9:return VIn((cks&ENHANCED_KEY)
356 ? (NULL)
357 : (m_bKPN?"\33Oy":"\33[5~")
358 );
359 case VK_INSERT:
360 case VK_NUMPAD0:return VIn((cks&ENHANCED_KEY)
361 ? ("\33Op")
362 : (m_bKPN?"\33[3~":"\33Op")
363 );
364 case VK_DELETE:
365 case VK_DECIMAL:return VIn((cks&ENHANCED_KEY)
366 ? ("\33On")
367 : (m_bKPN?"\33[3~":"\33On")
368 );
369 }
370
371 return FALSE;
372 #undefFUNKEY
373 #undefAROKEY
374 }
375 BOOL VIn(LPCTSTR str) {
376 if(!str)
377 return TRUE;
378 int l = strlen(str);
379 VERIFY(SendLiteral(str,l));
380 if(
381 (
382 Options[toEcho].m_StateU==TOption::stateYes
383 || Options[toEcho].m_StateU==TOption::stateNone
384 ) && (
385 Options[toEcho].m_StateH!=TOption::stateYes
386 || Options[toEcho].m_StateH==TOption::stateNone
387 )
388 ){
389 PreOutput();
390 for(;l>0;l--)
391 Output(*(str++));
392 PostOutput();
393 }
394 return TRUE;
395 }
396
397 UINT ParseParms() {
398 ASSERT(m_Sequenced>2);
399 m_Parms[m_nParms=0]=0;
400 m_ParmPtrs[m_nParms]=2;
401 BOOL bWas = FALSE;
402 for(UINT tmp=2;tmp<(m_Sequenced-1);tmp++){
403 if(isdigit(m_Sequence[tmp])){
404 m_Parms[m_nParms]*=10;
405 m_Parms[m_nParms]+=m_Sequence[tmp]-'0';
406 bWas = TRUE;
407 }else{
408 if((m_nParms+1)>=(sizeof(m_Parms)/sizeof(*m_Parms))){
409 TRACE0("Way too many parameters in ESC[ sequence\n");
410 return m_nParms=0;
411 }
412 m_Parms[++m_nParms]=0;
413 m_ParmPtrs[m_nParms]=tmp+1;
414 bWas = FALSE;
415 }
416 }
417 if(bWas)
418 m_nParms++;
419 return m_nParms;
420 }
421
422 void DoIL(int y,int n) {
423 VScroll(y,n,(y<=sr1)?sr1:-1);
424 }
425 void DoDL(int y,int n) {
426 VScroll(y,-n,(y<=sr1)?sr1:-1);
427 }
428
429
430 BOOL DoRI() {
431 m_CSBI.dwCursorPosition.Y--;
432 if(m_CSBI.dwCursorPosition.Y==(sr0-1)){
433 m_CSBI.dwCursorPosition.Y++;
434 DoIL(m_CSBI.dwCursorPosition.Y,1);
435 }
436 return TRUE;
437 }
438 BOOL DoIND(BOOL bCR=FALSE) {
439 m_CSBI.dwCursorPosition.Y++;
440 if(m_CSBI.dwCursorPosition.Y==sr1+1){
441 m_CSBI.dwCursorPosition.Y--;
442 DoDL(sr0,1);
443 }
444 if(bCR)
445 m_CSBI.dwCursorPosition.X=0;
446 return TRUE;
447 }
448 BOOL DoNEL() {
449 return DoIND(TRUE);
450 }
451
452 BOOL DoEBS() {
453 ASSERT(m_Sequenced>2);
454 ParseParms();
455 CHAR c = m_Sequence[m_Sequenced-1];
456 switch(c){
457 UINT tmp;
458 case '@':// ICH Insert blank characters (default:1)
459 // VT102 Feature
460 if(m_nParms==0 || m_nParms==1){
461 Flush();
462 HScroll(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,m_nParms?m_Parms[0]:1);
463 }else
464 TRACE0("Invalid number of blanks for ESC[@\n");
465 break;
466 case 'A':
467 case 'F': // With horizontal homing at the end?? VT102? rxvt?
468 Flush();
469 if(m_nParms==0)
470 m_CSBI.dwCursorPosition.Y--;
471 else
472 m_CSBI.dwCursorPosition.Y-=max(1,m_Parms[0]);
473 if(m_CSBI.dwCursorPosition.Y<(m_bOM?sr0:0))
474 m_CSBI.dwCursorPosition.Y=m_bOM?sr0:0;
475 if(c=='F')
476 m_CSBI.dwCursorPosition.X=0;
477 break;
478 case 'B':
479 case 'E': // With horizontal homing at the end?? VT102? rxvt?
480 Flush();
481 if(m_nParms==0)
482 m_CSBI.dwCursorPosition.Y++;
483 else
484 m_CSBI.dwCursorPosition.Y+=max(1,m_Parms[0]);
485 if(m_CSBI.dwCursorPosition.Y>(m_bOM?sr1:(m_CSBI.dwSize.Y-1)))
486 m_CSBI.dwCursorPosition.Y=m_bOM?sr1:(m_CSBI.dwSize.Y-1);
487 if(c=='E')
488 m_CSBI.dwCursorPosition.X=0;
489 break;
490 case 'C':
491 Flush();
492 if(m_nParms==0)
493 m_CSBI.dwCursorPosition.X++;
494 else
495 m_CSBI.dwCursorPosition.X+=max(1,m_Parms[0]);
496 if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X)
497 m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1;
498 break;
499 case 'D':
500 Flush();
501 if(m_nParms==0)
502 m_CSBI.dwCursorPosition.X--;
503 else
504 m_CSBI.dwCursorPosition.X-=max(1,m_Parms[0]);
505 if(m_CSBI.dwCursorPosition.X<0)
506 m_CSBI.dwCursorPosition.X=0;
507 break;
508 case 'G':// HPA
509 if(m_nParms<2){
510 Flush();
511 m_CSBI.dwCursorPosition.X=min(m_CSBI.dwSize.X-1,m_nParms?max(0,(int)m_Parms[0]-1):0);
512 }else
513 TRACE0("Invalid args for ESC[G\n");
514 break;
515 case 'H':// CUP
516 case 'f':// HVP
517 {
518 Flush();
519 if(m_nParms==0){
520 m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0;
521 }else if(m_nParms==1){
522 m_CSBI.dwCursorPosition.Y = max(
523 m_bOM?sr0:0,
524 min(
525 (m_bOM?sr0:0)+(int)m_Parms[0]-1,
526 m_CSBI.dwSize.Y-1
527 )
528 );
529 }else if(m_nParms==2){
530 m_CSBI.dwCursorPosition.Y = max(
531 m_bOM?sr0:0,
532 min(
533 (m_bOM?sr0:0)+(int)m_Parms[0]-1,
534 m_CSBI.dwSize.Y-1
535 )
536 );
537 m_CSBI.dwCursorPosition.X = max(
538 0,
539 min(
540 (int)m_Parms[1]-1,
541 m_CSBI.dwSize.X-1
542 )
543 );
544 }else{
545 TRACE0("Invalid arguments for ESC[H\n");
546 break;
547 }
548 }
549 break;
550 case 'J':
551 Flush();
552 if(m_nParms==0 || m_Parms[0]==0){
553 // Erase from cursor to the end of the screen.
554 FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,
555 (m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X) +
556 (m_CSBI.dwSize.Y-m_CSBI.dwCursorPosition.Y-1)*m_CSBI.dwSize.X,
557 ' ',m_Attrs);
558 }else if(m_Parms[0]==1){
559 // Erase from the beggining of the screen up to cursor.
560 FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwCursorPosition.Y+m_CSBI.dwCursorPosition.X+1,
561 ' ',m_Attrs);
562 }else if(m_Parms[0]==2){
563 // Erase entire screen area
564 FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,' ',m_Attrs);
565 }else
566 TRACE0("Invalid argument for ESC[J\n");
567 break;
568 case 'K':
569 Flush();
570 if(m_nParms==0 || m_Parms[0]==0){
571 // From cursor to the end of line
572 FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,
573 m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X,' ',m_Attrs);
574 }else if(m_Parms[0]==1){
575 // From beginning to cursor
576 FillScreen(0,m_CSBI.dwCursorPosition.Y,m_CSBI.dwCursorPosition.X+1,' ',m_Attrs);
577 }else if(m_Parms[0]==2){
578 // Entire line
579 FillScreen(0,m_CSBI.dwCursorPosition.Y,m_CSBI.dwSize.X,' ',m_Attrs);
580 }else
581 TRACE0("Invalid argument for ESC[K\n");
582 break;
583 case 'L':// IL - Insert Line(s) - VT102
584 if(m_nParms<2){
585 Flush();
586 DoIL(m_CSBI.dwCursorPosition.Y,m_nParms?m_Parms[0]:1);
587 }else
588 TRACE0("Invalid args for ESC[L\n");
589 break;
590 case 'M':// DL - Delete Line(s) - VT102
591 if(m_nParms<2){
592 Flush();
593 DoDL(m_CSBI.dwCursorPosition.Y,m_nParms?m_Parms[0]:1);
594 }else
595 TRACE0("Invalid args for ESC[M\n");
596 break;
597 case 'P':// DCH - Delete Character(s) - VT102
598 if(m_nParms<2){
599 Flush();
600 int dlc = m_nParms?m_Parms[0]:1;
601 HScroll(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,-dlc);
602 }else
603 TRACE0("Invalid args for ESC[P\n");
604 break;
605 case 'X':// ECH - Erase characters VT102
606 if(m_nParms<2){
607 Flush();
608 int ec = m_nParms?m_Parms[0]:1;
609 if((m_CSBI.dwCursorPosition.X+ec)>m_CSBI.dwSize.X)
610 ec = m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X;
611 FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,ec,' ',m_Attrs);
612 }else
613 TRACE0("Invalid args for ESC[X\n");
614 break;
615 case 'c':// DA - Device attribute
616 if(m_nParms==0 || m_Parms[0]==0){
617 SendLiteral("\33[?1;3c");// This is supposed to mean
618 // STP & AVO - not sure what
619 // is STP, though..
620 }else
621 TRACE0("Invalid argument for ESC[c\n");
622 break;
623 case 'd':// VPA
624 if(m_nParms<2){
625 Flush();
626 m_CSBI.dwCursorPosition.Y=min(m_CSBI.dwSize.Y-1,m_nParms?max(0,(int)m_Parms[0]-1):0);
627 }else
628 TRACE0("Invalid args for ESC[d\n");
629 break;
630 case 'g':// TBC - Tabulation clear
631 if(m_nParms==0 || m_Parms[0]==0){
632 Flush();
633 ClearTAB(m_CSBI.dwCursorPosition.X);
634 }else if(m_Parms[0]==3){
635 m_TABs[0]=-1;
636 }else
637 TRACE1("Invalid argument for ESC[g - %d\n",m_nParms?m_Parms[0]:-1);
638 break;
639 case 'h':// SM - Set Mode
640 {
641 BOOL bQ = FALSE;
642 for(tmp=0;tmp<m_nParms;tmp++){
643 switch(m_Parms[tmp]){
644 case 0:// This may be caused by '?' only
645 if(m_Sequence[m_ParmPtrs[tmp]]=='?'){
646 bQ=TRUE;
647 continue;
648 }
649 TRACE0("Wrong zeromode in SM/RM command\n");
650 break;
651 case 1:
652 if(bQ){
653 m_bCKM=TRUE;
654 }
655 break;
656 case 2:
657 m_ctG0=m_ctG1=NULL;// Designate USASCII for G0-G3?
658 break;
659 case 3:
660 if(bQ){
661 Flush();
662 COORD ns = { 132,m_CSBI.dwSize.Y };
663 ResizeWindow(ns);
664 }
665 break;
666 case 4:
667 if(bQ){
668 TRACE0("Set smooth scrolling\n");
669 }else{
670 Flush();
671 TRACE0("Insert Mode\n");
672 m_bIM = TRUE;
673 }
674 break;
675 case 5:
676 if(bQ){
677 Flush();
678 if(!m_bTR)
679 ReverseScreen();
680 m_bTR = TRUE;
681 SetAttrs();
682 TRACE0("Set black on white\n");
683 }
684 break;
685 case 6:
686 if(bQ){
687 Flush();
688 m_bOM = TRUE;
689 m_CSBI.dwCursorPosition.X=0;
690 m_CSBI.dwCursorPosition.Y=sr0;// ??? It was +1 ?
691 }
692 break;
693 case 7:
694 if(bQ){
695 Flush();
696 m_bAWM=TRUE;
697 }
698 break;
699 case 8:
700 if(bQ){
701 TRACE0("Autorepeat On\n");
702 }
703 break;
704 case 20:
705 if(!bQ){
706 // LNM - New Line Mode
707 m_bLNM = TRUE;
708 }
709 break;
710 case 40:
711 if(bQ){
712 TRACE0("Enable 80/132 switch\n");// ???
713 }
714 break;
715 case 66:
716 if(bQ){
717 TRACE0("KP - CS\n");
718 m_bKPN = FALSE;
719 }
720 break;
721 default:
722 TRACE1("Unsupported mode in SM command: %d\n",m_Parms[tmp]);
723 break;
724 }
725 bQ=FALSE;
726 }
727 }
728 break;
729 case 'l':// RM - Reset Mode
730 {
731 BOOL bQ = FALSE;
732 for(tmp=0;tmp<m_nParms;tmp++){
733 switch(m_Parms[tmp]){
734 case 0:// This may be caused by '?' only
735 if(m_Sequence[m_ParmPtrs[tmp]]=='?'){
736 bQ=TRUE;
737 continue;
738 }
739 TRACE0("Wrong zeromode in SM/RM command\n");
740 break;
741 case 1:
742 if(bQ){
743 m_bCKM=FALSE;
744 }
745 break;
746 case 2:
747 if(bQ){
748 m_bVT52=TRUE;
749 }
750 break;
751 case 3:
752 if(bQ){
753 Flush();
754 COORD ns = { 80,m_CSBI.dwSize.Y };
755 ResizeWindow(ns);
756 }
757 break;
758 case 4:
759 if(bQ){
760 TRACE0("Set jump scrolling\n");
761 }else{
762 Flush();
763 TRACE0("Overtype Mode\n");
764 m_bIM = FALSE;
765 }
766 break;
767 case 5:
768 if(bQ){
769 Flush();
770 if(m_bTR)
771 ReverseScreen();
772 m_bTR = FALSE;
773 SetAttrs();
774 TRACE0("Set white on black\n");
775 }
776 break;
777 case 6:
778 if(bQ){
779 Flush();
780 m_bOM = FALSE;
781 m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0;
782 }
783 break;
784 case 7:
785 if(bQ){
786 Flush();
787 m_bAWM=FALSE;
788 }
789 break;
790 case 8:
791 if(bQ){
792 TRACE0("Autorepeat Off\n");
793 }
794 break;
795 case 20:
796 if(!bQ){
797 // LNM - New Line Mode
798 m_bLNM = FALSE;
799 }
800 break;
801 case 40:
802 if(bQ){
803 TRACE0("Disable 80/132 switch\n");// ???
804 }
805 break;
806 case 66:
807 if(bQ){
808 TRACE0("KP - Numeric\n");
809 m_bKPN = TRUE;
810 }
811 break;
812 default:
813 TRACE1("Unsupported mode in RM command: %d\n",m_Parms[tmp]);
814 break;
815 }
816 bQ=FALSE;
817 }
818 }
819 break;
820 case 'm':
821 if(m_nParms==0){
822 attrs=0;
823 m_fgAttr=m_bgAttr=-1;
824 }else
825 for(tmp=0;tmp<m_nParms;tmp++){
826 switch(m_Parms[tmp]){
827 case 0:
828 attrs=0; m_fgAttr=m_bgAttr=-1; break;
829 case 1:
830 attrs|=attrBold; break;
831 case 21:
832 attrs&=~attrBold; break;
833 case 2:
834 case 22:
835 break;// *** LIGHT (as opposed to bold)
836 case 4:
837 attrs|=attrUnderline; break;
838 case 24:
839 attrs&=~attrUnderline; break;
840 case 5:
841 attrs|=attrBlink; break;
842 case 25:
843 attrs&=~attrBlink; break;
844 case 7:
845 attrs|=attrReverse; break;
846 case 27:
847 attrs&=~attrReverse; break;
848 case 30:
849 m_fgAttr=0; break;
850 case 40:
851 m_bgAttr=0; break;
852 case 31:
853 m_fgAttr=FOREGROUND_RED; break;
854 case 41:
855 m_bgAttr=BACKGROUND_RED; break;
856 case 32:
857 m_fgAttr=FOREGROUND_GREEN; break;
858 case 42:
859 m_bgAttr=BACKGROUND_GREEN; break;
860 case 33:
861 m_fgAttr=FOREGROUND_GREEN|FOREGROUND_RED; break;
862 case 43:
863 m_bgAttr=BACKGROUND_GREEN|BACKGROUND_RED; break;
864 case 34:
865 m_fgAttr=FOREGROUND_BLUE; break;
866 case 44:
867 m_bgAttr=BACKGROUND_BLUE; break;
868 case 35:
869 m_fgAttr=FOREGROUND_RED|FOREGROUND_BLUE; break;
870 case 45:
871 m_bgAttr=BACKGROUND_RED|BACKGROUND_BLUE; break;
872 case 36:
873 m_fgAttr=FOREGROUND_GREEN|FOREGROUND_BLUE; break;
874 case 46:
875 m_bgAttr=BACKGROUND_GREEN|BACKGROUND_BLUE; break;
876 case 37:
877 m_fgAttr=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; break;
878 case 47:
879 m_bgAttr=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE; break;
880 case 39:
881 m_fgAttr=-1; break;
882 case 49:
883 m_bgAttr=-1; break;
884 default:
885 TRACE1("Invalid attribute for ESC[m sequence - %u\n",m_Parms[tmp]);
886 break;
887 }
888 }
889 SetAttrs();
890 break;
891 case 'n':// DSR - Device Status Report
892 if(m_nParms==1){
893 switch(m_Parms[0]){
894 case 5:// Report Status
895 SendLiteral("\33[0n");
896 break;
897 case 6:// Report Cursor Position
898 Flush();
899 sprintf(sfCrap,"\33[%d;%dR",
900 (m_bOM?(m_CSBI.dwCursorPosition.Y-sr0):m_CSBI.dwCursorPosition.Y)+1,
901 m_CSBI.dwCursorPosition.X+1
902 );
903 SendLiteral(sfCrap);
904 break;
905 }
906 }else
907 TRACE0("Invalid DSR request\n");
908 break;
909 case 'r':
910 Flush();
911 if(m_nParms==2){
912 sr0=max(0,m_Parms[0]-1);
913 if(sr0>=m_CSBI.dwSize.Y)
914 sr0=m_CSBI.dwSize.Y-1;
915 sr1=max((UINT)sr0,m_Parms[1]-1);
916 if(sr1>=m_CSBI.dwSize.Y)
917 sr1=m_CSBI.dwSize.Y-1;
918 TRACE2("SCROLL{%d,%d}\n",(int)sr0,(int)sr1);
919 }else{
920 sr0=0; sr1 = m_CSBI.dwSize.Y-1;
921 }
922 m_CSBI.dwCursorPosition.X=0;
923 m_CSBI.dwCursorPosition.Y=sr0;
924 break;
925 case 'x': // DECREQTPARM- Request Terminal Parameters
926 // if parameter is zero - we'll send unsolicited reports when we exit SET-UP.
927 // if not - we won't. Actually, we won't, anyway.
928 // Actually, first value is not made up according to any standard that I know of
929 // It's to make vttest happy.
930 SendLiteral((m_nParms==0 || m_Parms[0]==0)?"\33[2;1;1;112;112;1;0x":"\33[3;1;1;112;112;1;0x");
931 break;
932 case 'y':// Invoke Confidence Test
933 if(m_nParms==2 && m_Parms[0]==2){
934 if(m_Parms[1]==0){
935 Flush();
936 Init();
937 FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,' ',m_Attrs);
938 m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0;
939 }else
940 TRACE1("Terminal is now invoking tests - %d\n",m_Parms[0]);
941 }else
942 TRACE0("Invalid args for ESC[y\n");
943 break;
944 default:
945 TRACE2("ESC[ SEQUENCE ENDING WITH '%c' AND %d PARS ",(CHAR)c,(INT)m_nParms);
946 for(tmp=0;tmp<m_nParms;tmp++)
947 TRACE1("[%d]",m_Parms[tmp]);
948 TRACE0("\n");
949 break;
950 }
951 m_Sequenced=0;
952 state=stateNone;
953 return TRUE;
954 }
955
956 BOOL DoPrintable(CHAR c){
957 if(m_Buffered>=(sizeof(m_Buffer)/sizeof(*m_Buffer)))
958 Flush();
959 if(m_CT && m_CT[(BYTE)c])
960 c = m_CT[(BYTE)c];
961 m_Buffer[m_Buffered].Char.AsciiChar=c;
962 m_Buffer[m_Buffered].Attributes=m_Attrs;
963 m_Buffered++;
964 return TRUE;
965 }
966 BOOL Flush() {
967 for(UINT tmp=0;tmp<m_Buffered;){
968 if(m_bRight){
969 if(!m_bAWM)
970 break;
971 DoNEL();
972 m_bRight=FALSE;
973 continue;
974 }
975 UINT chars = min(m_Buffered-tmp,(UINT)m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X);
976 COORD bs = {chars,1};
977 static
978 COORD bc = {0,0};
979 SMALL_RECT wr = {m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,
980 m_CSBI.dwSize.X-1,m_CSBI.dwCursorPosition.Y};
981 if(m_bIM && ((m_CSBI.dwCursorPosition.X+(int)chars)<m_CSBI.dwSize.X))
982 // Scroll to make place in insert mode
983 HScroll(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,chars);
984 VERIFY(::WriteConsoleOutput(hConsoleOutput,&m_Buffer[tmp],bs,bc,&wr));
985 m_CSBI.dwCursorPosition.X+=chars;
986 tmp+=chars;
987 if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X){
988 ASSERT(m_CSBI.dwCursorPosition.X==m_CSBI.dwSize.X);
989 m_bRight=TRUE;
990 m_CSBI.dwCursorPosition.X--;
991 }else{
992 m_bRight=FALSE;
993 }
994 }
995 m_Buffered=0;
996 //PulseOutput();
997 return TRUE;
998 }
999
1000 BOOL ProcessSingleChar(CHAR c) {
1001 switch(c){
1002 case 0:
1003 break;// Ignore NULLs
1004 case '\t':
1005 {
1006 Flush();
1007 for(int tmp=0;tmp<(sizeof(m_TABs)/sizeof(*m_TABs)) && m_TABs[tmp]>=0;tmp++){
1008 if(m_TABs[tmp]>m_CSBI.dwCursorPosition.X){
1009 m_CSBI.dwCursorPosition.X=m_TABs[tmp];
1010 break;
1011 }
1012 }
1013 if(tmp==(sizeof(m_TABs)/sizeof(*m_TABs)) || m_TABs[tmp]<0)
1014 m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1;
1015 if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X)
1016 m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1;
1017 }
1018 break;
1019 case '\n':// Handle this manually because of the glitch in windows handling..
1020 case '\13':// VT
1021 case '\14':// FF
1022 Flush();
1023 DoIND();
1024 break;
1025 case '\a':// bell
1026 Flush();
1027 MessageBeep(0xFFFFFFFF);
1028 break;
1029 case '\b':// back
1030 Flush();
1031 m_CSBI.dwCursorPosition.X--;
1032 if(m_CSBI.dwCursorPosition.X<0)
1033 m_CSBI.dwCursorPosition.X=0;
1034 break;
1035 case '\r':
1036 Flush();
1037 if(m_bLNM)
1038 DoIND();
1039 else
1040 m_CSBI.dwCursorPosition.X=0;
1041 break;
1042 case '\16':// SO - Select G1
1043 m_CT = m_ctG1;
1044 m_ctG = 1;
1045 break;
1046 case '\17':// SI - Select G0
1047 m_CT = m_ctG0;
1048 m_ctG = 0;
1049 break;
1050 case '\5':// ENQ - Transmit ANSWERBACK message
1051 return VIn(
1052 "From kintucky to kinecticut,\n"
1053 "Kinky kinglet kindly rules,\n"
1054 "Makin' KINs that're most kinetic, but,\n"
1055 "Please, admit, they're kinda kool!\n\n"
1056 );
1057 default:
1058 return FALSE;
1059 }
1060 return TRUE;
1061 }
1062
1063
1064 virtual BOOL Output(UINT c) {
1065 static
1066 COORDzero = {0,0};
1067 switch(state) {
1068 case stateEY52Seq1:
1069 m_vt52Y1=c-037-1;
1070 state=stateEY52Seq2;
1071 break;
1072 case stateEY52Seq2:
1073 m_vt52Y2=c-037-1;
1074 Flush();
1075 m_CSBI.dwCursorPosition.Y = max(
1076 m_bOM?sr0:0,
1077 min(
1078 (m_bOM?sr0:0)+(int)m_vt52Y1,
1079 m_CSBI.dwSize.Y-1
1080 )
1081 );
1082 m_CSBI.dwCursorPosition.X = max(
1083 0,
1084 min(
1085 m_vt52Y2,
1086 m_CSBI.dwSize.X-1
1087 )
1088 );
1089 state=stateNone;
1090 break;
1091 case stateEPSSeq:// Pound Sign
1092 switch(c){
1093 case '8':// DECALN - Screen Alignment Display
1094 Flush();
1095 FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,'E',FOREGROUND_RED|FOREGROUND_GREEN|
1096 FOREGROUND_BLUE);
1097 break;
1098 default:
1099 TRACE1("ESC# %c\n",c);
1100 break;
1101 }
1102 state = stateNone;
1103 break;
1104 case stateEPOSeq:// Parenthesis Opening
1105 switch(c){
1106 case 'A':
1107 case 'B':
1108 case '1':
1109 m_ctG0 =NULL;
1110 break;
1111 case '0':
1112 case '2':
1113 m_ctG0 = m_ctGraphs;
1114 break;
1115 default:
1116 TRACE1("Invalide ESC( %c\n",c);
1117 break;
1118 }
1119 if(m_ctG==0)
1120 m_CT = m_ctG0;
1121 state = stateNone;
1122 break;
1123 case stateEPCSeq:// Parenthesis Closing
1124 switch(c){
1125 case 'A':
1126 case 'B':
1127 case '1':
1128 m_ctG1 =NULL;
1129 break;
1130 case '0':
1131 case '2':
1132 m_ctG1 = m_ctGraphs;
1133 break;
1134 default:
1135 TRACE1("Invalide ESC( %c\n",c);
1136 break;
1137 }
1138 if(m_ctG)
1139 m_CT = m_ctG1;
1140 state = stateNone;
1141 break;
1142 case stateEBSeq:// Bracket
1143 if(ProcessSingleChar(c))
1144 break;
1145 if(m_Sequenced>=sizeof(m_Sequence)){
1146 m_bEBFailure=TRUE;
1147 m_Sequenced=2;
1148 }
1149 m_Sequence[m_Sequenced++]=c;
1150 if(isalpha(c) || c=='~' || c=='@'){// *** Maybe we should reconsider these critera
1151 if(m_bEBFailure){
1152 m_Sequenced=0;
1153 state = stateNone;
1154 }else
1155 DoEBS();
1156 }else if(c==030){ // CAN
1157 m_Sequenced=0;
1158 state = stateNone;
1159 // *** DO WE PUT OUT the checkerboard (error character?)
1160 }
1161 break;
1162 case stateESeq:// Escape
1163 if(m_bVT52){
1164 state=stateNone;
1165 switch(c){
1166 case 'A':
1167 Flush();
1168 if(m_nParms==0)
1169 m_CSBI.dwCursorPosition.Y--;
1170 else
1171 m_CSBI.dwCursorPosition.Y-=max(1,m_Parms[0]);
1172 if(m_CSBI.dwCursorPosition.Y<(m_bOM?sr0:0))
1173 m_CSBI.dwCursorPosition.Y=m_bOM?sr0:0;
1174 if(c=='F')
1175 m_CSBI.dwCursorPosition.X=0;
1176 break;
1177 case 'B':
1178 Flush();
1179 if(m_nParms==0)
1180 m_CSBI.dwCursorPosition.Y++;
1181 else
1182 m_CSBI.dwCursorPosition.Y+=max(1,m_Parms[0]);
1183 if(m_CSBI.dwCursorPosition.Y>(m_bOM?sr1:(m_CSBI.dwSize.Y-1)))
1184 m_CSBI.dwCursorPosition.Y=m_bOM?sr1:(m_CSBI.dwSize.Y-1);
1185 if(c=='E')
1186 m_CSBI.dwCursorPosition.X=0;
1187 break;
1188 case 'C':
1189 Flush();
1190 if(m_nParms==0)
1191 m_CSBI.dwCursorPosition.X++;
1192 else
1193 m_CSBI.dwCursorPosition.X+=max(1,m_Parms[0]);
1194 if(m_CSBI.dwCursorPosition.X>=m_CSBI.dwSize.X)
1195 m_CSBI.dwCursorPosition.X=m_CSBI.dwSize.X-1;
1196 break;
1197 case 'D':
1198 Flush();
1199 if(m_nParms==0)
1200 m_CSBI.dwCursorPosition.X--;
1201 else
1202 m_CSBI.dwCursorPosition.X-=max(1,m_Parms[0]);
1203 if(m_CSBI.dwCursorPosition.X<0)
1204 m_CSBI.dwCursorPosition.X=0;
1205 break;
1206 case 'F':
1207 m_CT=m_ctG1;
1208 m_ctG=1;
1209 break;
1210 case 'G':
1211 m_CT=m_ctG0;
1212 m_ctG=0;
1213 break;
1214 case 'H':
1215 Flush();
1216 m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0;
1217 break;
1218 case 'I':
1219 Flush();
1220 DoRI();
1221 break;
1222 case 'J':
1223 Flush();
1224 // Erase from cursor to the end of the screen.
1225 FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,
1226 (m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X) +
1227 (m_CSBI.dwSize.Y-m_CSBI.dwCursorPosition.Y-1)*m_CSBI.dwSize.X,
1228 ' ',m_Attrs);
1229 break;
1230 case 'K':
1231 Flush();
1232 FillScreen(m_CSBI.dwCursorPosition.X,m_CSBI.dwCursorPosition.Y,
1233 m_CSBI.dwSize.X-m_CSBI.dwCursorPosition.X,' ',m_Attrs);
1234 break;
1235 case 'Y':
1236 state=stateEY52Seq1;
1237 break;
1238 case 'Z':
1239 VIn("\33/Z");
1240 break;
1241 case '<':
1242 m_bVT52=FALSE;
1243 break;
1244 default:
1245 TRACE0("Invalid ESC sequence in VT52 mode\n");
1246 break;
1247 }
1248 }else{
1249 switch(c){
1250 case '[':
1251 ASSERT(m_Sequenced==1);
1252 m_Sequence[m_Sequenced++]=c;
1253 state = stateEBSeq;
1254 break;
1255 case 'H':// Set TAB at cursor
1256 InsertTAB(m_CSBI.dwCursorPosition.X);
1257 state = stateNone;
1258 break;
1259 case 'M':// Arrow Up and scroll if needed.
1260 Flush();
1261 DoRI();
1262 state = stateNone;
1263 break;
1264 case 'D':// Arrow Dn and scroll if needed.
1265 Flush();
1266 DoIND();
1267 state = stateNone;
1268 break;
1269 case 'E':// Next Line - about identical to \r\n
1270 Flush();
1271 DoNEL();
1272 state = stateNone;
1273 break;
1274 case 'c':// RIS - Reset to Initial State
1275 {
1276 Flush();
1277 Init();
1278 FillScreen(0,0,m_CSBI.dwSize.X*m_CSBI.dwSize.Y,' ',m_Attrs);
1279 m_CSBI.dwCursorPosition.X = m_CSBI.dwCursorPosition.Y = 0;
1280 }
1281 break;
1282 case '(':
1283 state = stateEPOSeq;
1284 break;
1285 case ')':
1286 state = stateEPCSeq;
1287 break;
1288 case '#':
1289 state = stateEPSSeq;
1290 break;
1291 case '=': // DECKPAM- Keypad sends sequences
1292 TRACE0("KP - CS\n");
1293 m_bKPN = FALSE;
1294 state = stateNone;
1295 break;
1296 case '>': // DECKPNM- Keypad sends numerics
1297 TRACE0("KP - Numeric\n");
1298 m_bKPN = TRUE;
1299 state = stateNone;
1300 break;
1301 case '7':// Save Cursor and charsets
1302 m_savedCTG0 = m_ctG0; m_savedCTG1 = m_ctG1; m_savedCT = m_CT;
1303 m_savedCTG=m_ctG;
1304 memmove(&m_savedCP,&m_CSBI.dwCursorPosition,sizeof(m_savedCP));
1305 m_savedAttrs = attrs;
1306 state = stateNone;
1307 break;
1308 case '8':// Restore cursor and charsets
1309 Flush();
1310 m_ctG0 = m_savedCTG0; m_ctG1 = m_savedCTG1; m_CT = m_savedCT;
1311 m_ctG=m_savedCTG;
1312 memmove(&m_CSBI.dwCursorPosition,&m_savedCP,sizeof(m_CSBI.dwCursorPosition));
1313 state = stateNone;
1314 attrs = m_savedAttrs;
1315 SetAttrs();
1316 break;
1317 default:
1318 TRACE1("ESCNON[ SEQ - '%c'\n",c);
1319 state = stateNone;
1320 break;
1321 }
1322 }
1323 break;
1324 default:
1325 case stateNone:
1326 ASSERT(state==stateNone);
1327 if(isprint(c&0x7F) || (c&0x7F)==0x7F){
1328 DoPrintable(c);
1329 }else{
1330 switch(c){
1331 case '\33':
1332 m_Sequenced=0;m_Sequence[m_Sequenced++]=c;
1333 state = stateESeq;
1334 break;
1335 default:
1336 if(!ProcessSingleChar(c))
1337 TRACE1("Unrecognized character 0x%02X\n",(WORD)c);
1338 break;
1339 }
1340 }
1341 m_bRight=FALSE;
1342 break;
1343 }
1344 return TRUE;
1345 }
1346
1347 virtual BOOL PreOutput() {
1348 return TRUE;
1349 }
1350 virtual BOOL PostOutput() {
1351 Flush();
1352 VERIFY(SetConsoleCursorPosition(hConsoleOutput,m_CSBI.dwCursorPosition));
1353 return TRUE;
1354 }
1355 BOOL PulseOutput() {
1356 Flush();
1357 VERIFY(SetConsoleCursorPosition(hConsoleOutput,m_CSBI.dwCursorPosition));
1358 return TRUE;
1359 }
1360
1361 virtual BOOL Init() {
1362 m_Sequenced=0;
1363 state = stateNone;
1364 attrs=0;
1365 DoNAWS();
1366 sr0 = 0; sr1 = m_CSBI.dwSize.Y-1;
1367 m_bRight = FALSE;
1368 m_Buffered=0;
1369 m_savedCT = m_CT = NULL;
1370 m_savedCTG0 = m_ctG0 = NULL;
1371 m_savedCTG1 = m_ctG1 = m_ctGraphs;
1372 m_savedCTG = m_ctG;
1373 m_savedCP.X=m_savedCP.Y=0;
1374 m_bKPN = TRUE;
1375 m_bCKM = FALSE;
1376 m_bAWM = TRUE;
1377 m_bOM = FALSE;
1378 m_bLNM = FALSE;
1379 m_bIM = FALSE;
1380 m_bVT52 = FALSE;
1381 m_bTR = FALSE;
1382 m_bgAttr=-1;
1383 m_fgAttr=-1;
1384 SetAttrs();
1385 InitCT();
1386 InitTAB();
1387 SizeWindowToAll();
1388 return TRUE;
1389 }
1390
1391 virtual LPCTSTR GetTitle() {
1392 static
1393 CHAR consoleTitle[1024];
1394 if(TTTermType<0)
1395 return "WEIRDO";
1396 sprintf(consoleTitle,"%s [%dx%d]",TTypes[TTTermType].m_Name,m_CSBI.dwSize.X,m_CSBI.dwSize.Y);
1397 return consoleTitle;
1398 }
1399
1400 BOOL SizeWindowToAll() {
1401 SMALL_RECT wi = {0,0,
1402 min(m_CSBI.dwSize.X-2,m_CSBI.dwMaximumWindowSize.X-1),
1403 min(m_CSBI.dwSize.Y-1,m_CSBI.dwMaximumWindowSize.Y-1)
1404 };
1405 SetConsoleWindowInfo(hConsoleOutput,TRUE,&wi);
1406 wi.Right++;
1407 return SetConsoleWindowInfo(hConsoleOutput,TRUE,&wi);
1408 }
1409
1410 BOOL ClearTAB(INT tab) {
1411 for(int tmp=0;tmp<(sizeof(m_TABs)/sizeof(*m_TABs)) && m_TABs[tmp]>=0;tmp++)
1412 if(tab==m_TABs[tmp]){
1413 memmove(&m_TABs[tmp],&m_TABs[tmp+1],sizeof(m_TABs)-sizeof(*m_TABs)*(tmp+1));
1414 m_TABs[(sizeof(m_TABs)/sizeof(*m_TABs))-1]=-1;
1415 return TRUE;
1416 }
1417 return FALSE;
1418 }
1419 BOOL InsertTAB(INT tab) {
1420 for(int tmp=0;tmp<(sizeof(m_TABs)/sizeof(*m_TABs));tmp++){
1421 if(tab==m_TABs[tmp])
1422 return TRUE;
1423 else if(m_TABs[tmp]>tab || m_TABs[tmp]<0){
1424 if(tmp!=((sizeof(m_TABs)/sizeof(*m_TABs))-1))
1425 memmove(&m_TABs[tmp+1],&m_TABs[tmp],sizeof(m_TABs)-sizeof(*m_TABs)*(tmp+1));
1426 m_TABs[tmp]=tab;
1427 return TRUE;
1428 }
1429 }
1430 return FALSE;
1431 }
1432 void InitTAB() {
1433 ASSERT(m_CSBI.dwSize.X<=(sizeof(m_TABs)/sizeof(*m_TABs)));
1434 for(int tmp=0,tab=0;tmp<m_CSBI.dwSize.X;tmp+=8)
1435 m_TABs[tab++]=tmp;
1436 m_TABs[tab++]=-1;
1437 }
1438 void InitCT() {
1439 memset(m_ctGraphs,0,sizeof(m_ctGraphs));
1440 m_ctGraphs['_'] = ' ';// Blank
1441 m_ctGraphs['`'] = 4;//Diamond
1442 m_ctGraphs['a'] = (CHAR)0xB0;// Checkerboard
1443 m_ctGraphs['b'] = (CHAR)0x1D;// Digigraph: HT
1444 m_ctGraphs['c'] = (CHAR)0x1F;// Digigtaph: FF
1445 m_ctGraphs['d'] = (CHAR)0x11;// Digigraph: CR
1446 m_ctGraphs['e'] = (CHAR)0x19; // Digigraph: LF
1447 m_ctGraphs['f'] = (CHAR)0xF8;// Degree Symbol
1448 m_ctGraphs['g'] = (CHAR)0xF1;// +/i Symbol
1449 m_ctGraphs['h'] = (CHAR)0x1C;// Digigraph: NL
1450 m_ctGraphs['i'] = (CHAR)0x17;// Digigraph: VT
1451 m_ctGraphs['j'] = (CHAR)0xD9;// Lower-Right Corner
1452 m_ctGraphs['k'] = (CHAR)0xBF;// Upper-Right Corner
1453 m_ctGraphs['l'] = (CHAR)0xDA; // Upper-Left Corner
1454 m_ctGraphs['m'] = (CHAR)0xC0;// Lower-Left Corner
1455 m_ctGraphs['n'] = (CHAR)0xC5;// Crossing Lines
1456 m_ctGraphs['o'] = (CHAR)0xC4;// Horiz Line - scan 1
1457 m_ctGraphs['p'] = (CHAR)0xC4;// Horiz Line - scan 3
1458 m_ctGraphs['q'] = (CHAR)0xC4;// Horiz Line - scan 5
1459 m_ctGraphs['r'] = (CHAR)0xC4;// Horiz Line - scan 7
1460 m_ctGraphs['s'] = (CHAR)0xC4;// Horiz Line - scan 9
1461 m_ctGraphs['t'] = (CHAR)0xC3;// Left 'T' - |-
1462 m_ctGraphs['u'] = (CHAR)0xB4;// Right 'T' - -|
1463 m_ctGraphs['v'] = (CHAR)0xC1;// Bottom 'T' - _|_
1464 m_ctGraphs['w'] = (CHAR)0xC2;// Top 'T' - -,-
1465 m_ctGraphs['x'] = (CHAR)0xB3;// Vertical Bar - |
1466 m_ctGraphs['y'] = (CHAR)0xF3;// Less or equal <=
1467 m_ctGraphs['z'] = (CHAR)0xF2; // Greater or equal >=
1468 m_ctGraphs['{'] = (CHAR)0xE3;// Pi symbol
1469 m_ctGraphs['|'] = (CHAR)0xD8;// Not equal !=
1470 m_ctGraphs['}'] = (CHAR)0xE0;// UK pound symbol
1471 m_ctGraphs['~'] = (CHAR)0xF9;// Centered dot
1472 }
1473}
1474 TT_VT100;
1475
1476DWORD CVT100::dummyWritten = 0;
1477CHAR CVT100::m_ctGraphs[256];
1478// ?? CHAR CVT100::sfCrap[256];
diff --git a/help/kinsole.cnt b/help/kinsole.cnt
new file mode 100644
index 0000000..9a8af90
--- a/dev/null
+++ b/help/kinsole.cnt
@@ -0,0 +1,9 @@
1:Base KINSole.hlp>Standard
2:Title KINSole
31 KINSole
42 About KINSole=About
52 Using KINSole=Using
62 Command Line Options=CmdOptions
72 Keyboard Shortcuts=HotKeys
82 Beta Notes=BetaNotes
92 Beta News=News
diff --git a/help/kinsole.hpj b/help/kinsole.hpj
new file mode 100644
index 0000000..62b1b55
--- a/dev/null
+++ b/help/kinsole.hpj
@@ -0,0 +1,17 @@
1; This file is maintained by HCW. Do not modify this file directly.
2
3[OPTIONS]
4HCW=0
5COMPRESS=12 Hall Zeck
6LCID=0x409 0x0 0x0 ;English (United States)
7REPORT=Yes
8CONTENTS=About
9TITLE=KINSole
10CNT=kinsole.cnt
11HLP=KINSOLE.HLP
12
13[FILES]
14KINSole.rtf
15
16[WINDOWS]
17Standard="",(32,64,949,175),28932,(r14876671),(r12632256),f2
diff --git a/help/kinsole.rtf b/help/kinsole.rtf
new file mode 100644
index 0000000..2cfd296
--- a/dev/null
+++ b/help/kinsole.rtf
@@ -0,0 +1,97 @@
1{\rtf1\ansi
2@{\footnote
3THIS FILE WAS AUTOMATICALLY GENERATED FROM XML DOCUMENT.
4DO NOT MODIFY THIS FILE DIRECTLY. EDIT XML DOCUMENT INSTEAD
5}
6{\fonttbl{\f0\froman Times New Roman;}{\f1\fswiss Arial;}{\f3\froman Symbol;}}{\colortbl;
7 \red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;
8 \red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;
9 \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;
10 \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
11
12\pard\plain\keepn
13#{\footnote About}
14${\footnote About KINSole}
15{ \f1\fs18\b\sb120 About KINSole}
16\par\sa120\sb120\qj\pard \f1\fs18\sb120 {\b KINSole} is our {\i Win32} implementation of client side of the {\i telnet} protocol described in details in the {\uldb {\b RFC854}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc854.txt")} and related RFCs (namely {\uldb {\b RFC855}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc855.txt")}, {\uldb {\b RFC857}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc857.txt")}, {\uldb {\b RFC1091}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc1091.txt")}, {\uldb {\b RFC1073}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc1073.txt")}, {\uldb {\b RFC1572}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc1572.txt")} and others). It uses {\i Win32} console and, therefore, can be run both windowed and in fullscreen mode.
17\par\sa120\sb120\qj\pard \f1\fs18\sb120
18\par\sa120\sb120\qj\pard \f1\fs18\sb120 {\b {\i Enjoy!}}
19{
20\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/")}
21\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:
22\par The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
23\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.
24}
25\par \sa0\sb120\ql \f1\fs16 Author: {\b\uldb\cf11 Michael Krelin ({\i hacker@klever.net})}{\v %!ExecFile("mailto:hacker@klever.net")}
26\par \sa0\sb0 Fan mail send to {\i\uldb gefilte@klever.net}{\v %!ExecFile("mailto:gefilte@klever.net")}
27\page
28
29\pard\plain\keepn
30#{\footnote News}
31${\footnote Beta News}
32{ \f1\fs18\b\sb120 Beta News}
33\par\pard\plain\f1\fs24\qc\cf2\b 1.00 Beta 3 - August 19st, 2002
34\par\pard\plain\fi0\li0\f1\fs18 \bullet No changes in code. License change.
35\par\pard\plain\f1\fs24\qc\cf2\b 1.00 Beta 2 - March 7th, 1998
36\par\pard\plain\fi0\li0\f1\fs18 \bullet Better copying from {\b KINSole} window.
37\par\pard\plain\fi0\li0\f1\fs18 \bullet Better handling of cursor position when resizing window.
38\par\pard\plain\fi0\li0\f1\fs18 \bullet Sending {\b CR/LF} pair when pressing {\b ENTER}. This is of help when telnetting to non-telnet ports.
39\par\pard\plain\fi0\li0\f1\fs18 \bullet Corrected bug, preventing {\b KINSole} from pasting text to remote twice.
40\par\pard\plain\fi0\li0\f1\fs18 \bullet Improved handling of echoing. Previously {\b KINSole} didn't turn echo off on some systems, namely {\b Solaris}.
41\par\pard\plain\fi0\li0\f1\fs18 \bullet Typo causing {\b KINSole} not to show diamond characters in {\b VT10x} mode corrected.
42\par\pard\plain\fi0\li0\f1\fs18 \bullet {\b GPF} when invoking {\b KINSole} with {\b -t} option fixed.
43\par\pard\plain\fi0\li0\f1\fs18 \bullet Hotkey ({\b Alt-INS}) for copy operation added. Not supposed to work under {\b\cf6 Windows NT}.
44\par\pard\plain\fi0\li0\f1\fs18 \bullet {\b Paste} is made aware of local echoing.
45\par\pard\plain\fi0\li0\f1\fs18 \bullet Default terminal type when telnetting to non-telnet port is now {\b TTY}.
46\par\pard\plain\fi0\li0\f1\fs18 \bullet {\b Timing Mark} telnet option ({\uldb {\b RFC860}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc860.txt")}) implemented ({\b Alt-T}).
47\par\pard\plain\fi0\li0\f1\fs18 \bullet Improved handling of window icon when starting from other {\i Win32} command line application.
48\page
49
50\pard\plain\keepn
51#{\footnote Using}
52${\footnote Using KINSole}
53{ \f1\fs18\b\sb120 Using {\b KINSole}}
54\par\sa120\sb120\qj\pard \f1\fs18\sb120 You may run {\b KINSole} from your MS-DOS prompt by typing '{\i kinsole host port}'.
55\par\sa120\sb120\qj\pard \f1\fs18\sb120 If you need to know more about custom options, please proceed to the {\uldb Command Line Options}{\v CmdOptions} section.
56\page
57
58\pard\plain\keepn
59#{\footnote CmdOptions}
60${\footnote Command Line Options}
61{ \f1\fs18\b\sb120 Command Line Options}
62\par\sa120\sb120\qj\pard \f1\fs18\sb120 Usage:
63\par\sa120\sb120\qj\pard \f1\fs18\sb120 KINSole [{\i options} ]{\i host}[ {\i port}]
64\par\sa120\sb120\qj\pard \f1\fs18\sb120 Available options are:\pard
65\par \fi0\li0 \bullet {\b -r {\i ##}} or {\b -{\i ##}} - Try to set the number of rows in console screen buffer.
66\par \fi0\li0 \bullet {\b -c {\i ##}} - Try to set the number of columns in console screenbuffer.
67\par \fi0\li0 \bullet
68\par\sa120\sb120\qj\f1\fs16 Note: Changing of console's screenbuffer size either from command line or on remote host's request (ESC[?3h vt100/vt102 control sequence) may not work when in fullscreen mode.
69\par \fi0\li0 \bullet {\b -l {\i username}} - Pass username to remote server in environment if remote server allows.
70\par \fi0\li0 \bullet {\b -e {\i var}={\i val}} - Pass environment variable to remote server.
71\par \fi0\li0 \bullet {\b -v {\i var}={\i val}} - Pass user environment variable to remote server.
72\par \fi0\li0 \bullet {\b -t {\i termtype}} - Change preferred terminal type to pass to remote server. This option does not really force specific terminal emulation. Final decision on terminal type is left up to server. Both sides are supposed to negotiate terminal type when connecting so that both sides may feel satisfied. Default preference is {\b vt102}.\pard
73\page
74
75\pard\plain\keepn
76#{\footnote HotKeys}
77${\footnote Hot Keys}
78{ \f1\fs18\b\sb120 Hot Keys}
79\par\sa120\sb120\qj\pard \f1\fs18\sb120 While running {\b KINSole} you may use these key combinations:\pard
80\par \fi0\li0 \bullet {\b Alt-X/Alt-Q} - Terminate telnet session and leave {\b KINSole}.
81\par \fi0\li0 \bullet {\b Alt-Y} - Send {\b AYT (Are You There)} telnet command. Remote host (if it supports telnet protocol as it's supposed to) should provide you with visible/printable/audible feedback stating that it's alive. You may want to use it when running program which takes unusually long time to finish and you suspect that your connection is dead.
82\par \fi0\li0 \bullet {\b Shift-INS} Paste text from Windows Clipboard.
83\par \fi0\li0 \bullet {\b Ctrl-Break} Send {\b IP (Interrupt Process)} telnet command. Usually effectively equivalent to Ctrl-C, but it's up to server to decide what to do in each case.
84\par \fi0\li0 \bullet {\b Alt-INS} - Invoke {\b copying} from {\b KINSole} screen buffer.
85\par \fi0\li0 \bullet {\b Alt-T} - Send {\b TIMING-MARK} request. As soon as response comes {\b KINSole} will flash window thrice or beep if window handle is not available for some reason.\pard
86\page
87
88\pard\plain\keepn
89#{\footnote BetaNotes}
90${\footnote Beta Notes}
91{ \f1\fs18\b\sb120 Beta Notes}
92\par\sa120\sb120\qj\pard \f1\fs18\sb120 A few things you may want to know about this Beta Release:\pard
93\par \fi0\li0 \bullet Only two terminal emulation modules are included in this beta release - one for dumb terminal and one for vt100/102. If you try to select ANSI terminal type vt100 emulation will be selected, which is actually close enough to ANSI so you shouldn't suffer too much. Why would one want to use ANSI terminal emulation, anyway?
94\par \fi0\li0 \bullet Telnet {\b LINEMODE} option ({\uldb {\b RFC1184}}{\v %!ExecFile("http://www.rfc-editor.org/rfc/rfc1184.txt")}) is still to come.
95\par \fi0\li0 \bullet Pasting of text using console toolbar button may cause {\b KINSole} to lock up. Use {\b Shift-INS} instead.\pard
96\page
97} \ No newline at end of file
diff --git a/help/kinsole.xml b/help/kinsole.xml
new file mode 100644
index 0000000..7d15eed
--- a/dev/null
+++ b/help/kinsole.xml
@@ -0,0 +1,72 @@
1<?xml version="1.0"?>
2<winhelp>
3 <topic id="About" title="About KINSole">
4 <heading scroll="no">About KINSole</heading>
5 <p><kin>KINSole</kin> is our <term>Win32</term> implementation of client side of the <term>telnet</term> protocol described in details in the <rfc num="854"/> and related RFCs (namely <rfc num="855"/>, <rfc num="857"/>, <rfc num="1091"/>, <rfc num="1073"/>, <rfc num="1572"/> and others). It uses <term>Win32</term> console and, therefore, can be run both windowed and in fullscreen mode.</p>
6 <p/>
7 <p><b><i>Enjoy!</i></b></p>
8 <license years="1998, 2002"/>
9 <credits/>
10 </topic>
11 <topic id="News" title="Beta News">
12 <heading scroll="no">Beta News</heading>
13 <newsfor version="1.00 Beta 3" date="August 19st, 2002">
14 <ni>No changes in code. License change.</ni>
15 </newsfor>
16 <newsfor version="1.00 Beta 2" date="March 7th, 1998">
17 <ni>Better copying from <kin>KINSole</kin> window.</ni>
18 <ni>Better handling of cursor position when resizing window.</ni>
19 <ni>Sending <b>CR/LF</b> pair when pressing <b>ENTER</b>. This is of help when telnetting to non-telnet ports.</ni>
20 <ni>Corrected bug, preventing <kin>KINSole</kin> from pasting text to remote twice.</ni>
21 <ni>Improved handling of echoing. Previously <kin>KINSole</kin> didn't turn echo off on some systems, namely <b>Solaris</b>.</ni>
22 <ni>Typo causing <kin>KINSole</kin> not to show diamond characters in <b>VT10x</b> mode corrected.</ni>
23 <ni><b>GPF</b> when invoking <kin>KINSole</kin> with <b>-t</b> option fixed.</ni>
24 <ni>Hotkey (<b>Alt-INS</b>) for copy operation added. Not supposed to work under <product>Windows NT</product>.</ni>
25 <ni><b>Paste</b> is made aware of local echoing.</ni>
26 <ni>Default terminal type when telnetting to non-telnet port is now <b>TTY</b>.</ni>
27 <ni><b>Timing Mark</b> telnet option (<rfc num="860"/>) implemented (<b>Alt-T</b>).</ni>
28 <ni>Improved handling of window icon when starting from other <term>Win32</term> command line application.</ni>
29 </newsfor>
30 </topic>
31 <topic id="Using" title="Using KINSole">
32 <heading scroll="no">Using <kin>KINSole</kin></heading>
33 <p>You may run <kin>KINSole</kin> from your MS-DOS prompt by typing '<i>kinsole host port</i>'.</p>
34 <p>If you need to know more about custom options, please proceed to the <a href="#CmdOptions">Command Line Options</a> section.</p>
35 </topic>
36 <topic id="CmdOptions" title="Command Line Options">
37 <heading scroll="no">Command Line Options</heading>
38 <p>Usage:</p>
39 <p>KINSole [<i>options</i> ]<i>host</i>[ <i>port</i>]</p>
40 <p>Available options are:</p>
41 <ul>
42 <li><b>-r <i>##</i></b> or <b>-<i>##</i></b> - Try to set the number of rows in console screen buffer.</li>
43 <li><b>-c <i>##</i></b> - Try to set the number of columns in console screenbuffer.</li>
44 <li><note>Note: Changing of console's screenbuffer size either from command line or on remote host's request (ESC[?3h vt100/vt102 control sequence) may not work when in fullscreen mode.</note></li>
45 <li><b>-l <i>username</i></b> - Pass username to remote server in environment if remote server allows.</li>
46 <li><b>-e <i>var</i>=<i>val</i></b> - Pass environment variable to remote server.</li>
47 <li><b>-v <i>var</i>=<i>val</i></b> - Pass user environment variable to remote server.</li>
48 <li><b>-t <i>termtype</i></b> - Change preferred terminal type to pass to remote server. This option does not really force specific terminal emulation. Final decision on terminal type is left up to server. Both sides are supposed to negotiate terminal type when connecting so that both sides may feel satisfied. Default preference is <b>vt102</b>.</li>
49 </ul>
50 </topic>
51 <topic id="HotKeys" title="Hot Keys">
52 <heading scroll="no">Hot Keys</heading>
53 <p>While running <kin>KINSole</kin> you may use these key combinations:</p>
54 <ul>
55 <li><b>Alt-X/Alt-Q</b> - Terminate telnet session and leave <kin>KINSole</kin>.</li>
56 <li><b>Alt-Y</b> - Send <b>AYT (Are You There)</b> telnet command. Remote host (if it supports telnet protocol as it's supposed to) should provide you with visible/printable/audible feedback stating that it's alive. You may want to use it when running program which takes unusually long time to finish and you suspect that your connection is dead.</li>
57 <li><b>Shift-INS</b> Paste text from Windows Clipboard.</li>
58 <li><b>Ctrl-Break</b> Send <b>IP (Interrupt Process)</b> telnet command. Usually effectively equivalent to Ctrl-C, but it's up to server to decide what to do in each case.</li>
59 <li><b>Alt-INS</b> - Invoke <b>copying</b> from <kin>KINSole</kin> screen buffer.</li>
60 <li><b>Alt-T</b> - Send <b>TIMING-MARK</b> request. As soon as response comes <kin>KINSole</kin> will flash window thrice or beep if window handle is not available for some reason.</li>
61 </ul>
62 </topic>
63 <topic id="BetaNotes" title="Beta Notes">
64 <heading scroll="no">Beta Notes</heading>
65 <p>A few things you may want to know about this Beta Release:</p>
66 <ul>
67 <li>Only two terminal emulation modules are included in this beta release - one for dumb terminal and one for vt100/102. If you try to select ANSI terminal type vt100 emulation will be selected, which is actually close enough to ANSI so you shouldn't suffer too much. Why would one want to use ANSI terminal emulation, anyway?</li>
68 <li>Telnet <b>LINEMODE</b> option (<rfc num="1184"/>) is still to come.</li>
69 <li>Pasting of text using console toolbar button may cause <kin>KINSole</kin> to lock up. Use <b>Shift-INS</b> instead.</li>
70 </ul>
71 </topic>
72</winhelp>
diff --git a/install/custom.rch b/install/custom.rch
new file mode 100644
index 0000000..8b3a590
--- a/dev/null
+++ b/install/custom.rch
@@ -0,0 +1,3 @@
1KINSole.ex_ RCDATA DISCARDABLE "../release/kinsole.ex_"
2KINSole.hl_ RCDATA DISCARDABLE "../release/kinsole.hl_"
3KINSole.cn_ RCDATA DISCARDABLE "../release/kinsole.cn_"
diff --git a/install/install.cpp b/install/install.cpp
new file mode 100644
index 0000000..e6f4e5a
--- a/dev/null
+++ b/install/install.cpp
@@ -0,0 +1,65 @@
1#include "resource.h"
2#include "../shared-code/install.h"
3
4 #define KINAME"KINSole 1.00 Beta 3"
5 #define SKINAME"KINSole"
6
7BOOL Install(void)
8{
9STRING tPath = strFETCH_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.",SKINAME "Path");
10STRING kPath = strFETCH_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.","KINPath");
11LPCSTR qPath = ((LPCSTR)tPath)?(LPCSTR)tPath:(((LPCSTR)kPath)?(LPSTR)kPath:"C:\\Program Files\\Klever\\Nothings");
12STRING path = REQUESTPATH(" " KINAME,"Note: KINSole program file will be installed into your windows directory so that you can rely on it's presence in your search path\nEnter destination path:",qPath);
13 if(!path)
14 return NULL;
15STRING winDir(_MAX_PATH);
16
17 GetWindowsDirectory(winDir,_MAX_PATH);
18 INSTALLFILE("KINSole.ex_",winDir,"KINSole.exe");
19 MAKE_PATH(path);
20STRING shortPath = GET_SHORT_PATH(path);
21 if(!shortPath){
22 MessageBox(NULL,"Failed to install " KINAME " in specified directory",NULL,MB_ICONERROR|MB_OK);
23 return FALSE;
24 }
25 if(!(
26 INSTALLFILE("KINSole.hl_",path,"KINSole.hlp") &&
27 INSTALLFILE("KINSole.cn_",path,"KINSole.cnt")
28 )){
29 MessageBox(NULL,"Failed to install " KINAME " in specified directory",NULL,MB_ICONERROR|MB_OK);
30 return FALSE;
31 }
32 ADDMENU("Accessories\\Klever Co.","KINSole Help",path,SKINAME ".hlp");
33 strSET_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.", SKINAME "Path",path);
34 strSET_REG_KEY(HKEY_LOCAL_MACHINE,"Software\\Klever Group, Inc.","KINPath",path);
35FILE* inf=CREATE_INF_FILE(path, SKINAME ".INF");
36 if(!inf){
37 MessageBox(NULL,"Failed to install " KINAME,NULL,MB_ICONERROR|MB_OK);
38 return FALSE;
39 }
40 INF_FILE_HEADER(inf);
41 INF_FILE_SECTION(inf,"Uninstall");
42 fprintf(inf,"AddReg=kFiles\nDelReg=kReg\nUpdateInis=kMenu\n");
43
44 INF_FILE_SECTION(inf,"kFiles");
45 INF_REMOVE_ROOT(inf,SKINAME "Files",shortPath);
46 INF_REMOVE_HELP_FILE(inf,SKINAME "Files",SKINAME);
47 INF_REMOVE_FILE(inf,SKINAME "Files",SKINAME ".inf");
48
49 INF_REMOVE_ROOT(inf,SKINAME "WFiles",winDir);
50 INF_REMOVE_FILE(inf,SKINAME "WFiles",SKINAME ".exe");
51
52 INF_FILE_SECTION(inf,"kReg");
53 INF_UNINSTALL_REG(inf,SKINAME);
54
55 INF_FILE_SECTION(inf,"kMenu");
56 INF_MENU_GROUP(inf,1,"Accessories\\Klever Co.");
57 INF_MENU_ITEM(inf,1,"KINSole Help");
58 fclose(inf);
59
60 REG_UNINSTALL_COMMAND(SKINAME,"Klever " KINAME,shortPath,SKINAME ".INF","Uninstall");
61
62 MessageBox(NULL,KINAME " installed successfully, you may now run it from command line, read documentation in Programs/Accessories/Klever Co. menu or simply remove it using Control Panel Add/Remove Programs applet."," Rejoice!",MB_ICONINFORMATION|MB_OK);
63
64 return TRUE;
65}
diff --git a/install/install.rc b/install/install.rc
new file mode 100644
index 0000000..d7780b6
--- a/dev/null
+++ b/install/install.rc
@@ -0,0 +1,182 @@
1//Microsoft Developer Studio generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/////////////////////////////////////////////////////////////////////////////
16// English (U.S.) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19#ifdef _WIN32
20LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21#pragma code_page(1252)
22#endif //_WIN32
23
24/////////////////////////////////////////////////////////////////////////////
25//
26// Dialog
27//
28
29#if defined(APSTUDIO_INVOKED) || defined(FALSE)
30#if defined(APSTUDIO_INVOKED)
31IDD_INSTALLING$(FALSE) DIALOGEX 0, 0, 200, 74
32#else
33IDD_INSTALLING DIALOGEX 0, 0, 200, 74
34#endif
35STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP
36FONT 8, "MS Sans Serif", 0, 0, 0x1
37BEGIN
38 PUSHBUTTON "Cancel",IDCANCEL,143,53,50,14,BS_CENTER | BS_VCENTER |
39 BS_NOTIFY | BS_FLAT,WS_EX_DLGMODALFRAME
40 CONTROL "Animate1",IDC_DISKS,"SysAnimate32",ACS_TRANSPARENT |
41 ACS_AUTOPLAY | WS_TABSTOP,161,7,32,32
42 LTEXT "",IDC_STATE,7,7,150,32,SS_NOPREFIX | SS_NOTIFY
43 CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",0x0,7,45,
44 186,7,WS_EX_DLGMODALFRAME
45END
46#endif
47
48IDD_PATH DIALOGEX 0, 0, 255, 73
49STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP |
50 WS_VISIBLE | WS_CAPTION
51EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
52FONT 8, "MS Sans Serif", 0, 0, 0x1
53BEGIN
54 LTEXT "",IDC_PROMPT,7,7,241,30
55 EDITTEXT IDC_PATH,7,37,195,12,ES_AUTOHSCROLL
56 PUSHBUTTON "B&rowse..",IDC_BROWSE,208,37,40,12
57 DEFPUSHBUTTON "OK",IDOK,69,52,50,14
58 PUSHBUTTON "Cancel",IDCANCEL,135,52,50,14
59END
60
61
62/////////////////////////////////////////////////////////////////////////////
63//
64// DESIGNINFO
65//
66
67#ifdef APSTUDIO_INVOKED
68GUIDELINES DESIGNINFO DISCARDABLE
69BEGIN
70 "IDD_INSTALLING$(FALSE)", DIALOG
71 BEGIN
72 LEFTMARGIN, 7
73 RIGHTMARGIN, 193
74 TOPMARGIN, 7
75 BOTTOMMARGIN, 67
76 HORZGUIDE, 39
77 END
78
79 IDD_PATH, DIALOG
80 BEGIN
81 LEFTMARGIN, 7
82 RIGHTMARGIN, 248
83 VERTGUIDE, 202
84 VERTGUIDE, 208
85 TOPMARGIN, 7
86 BOTTOMMARGIN, 66
87 HORZGUIDE, 37
88 END
89END
90#endif // APSTUDIO_INVOKED
91
92
93#ifdef APSTUDIO_INVOKED
94/////////////////////////////////////////////////////////////////////////////
95//
96// TEXTINCLUDE
97//
98
991 TEXTINCLUDE DISCARDABLE
100BEGIN
101 "resource.h\0"
102END
103
1042 TEXTINCLUDE DISCARDABLE
105BEGIN
106 "#include ""afxres.h""\r\n"
107 "\0"
108END
109
1103 TEXTINCLUDE DISCARDABLE
111BEGIN
112 "#include ""custom.rch""\0"
113END
114
115#endif // APSTUDIO_INVOKED
116
117
118/////////////////////////////////////////////////////////////////////////////
119//
120// Icon
121//
122
123// Icon with lowest ID value placed first to ensure application icon
124// remains consistent on all systems.
125IDI_ICON ICON DISCARDABLE "../shared-data/install-icon.ico"
126
127#ifndef _MAC
128/////////////////////////////////////////////////////////////////////////////
129//
130// Version
131//
132
133VS_VERSION_INFO VERSIONINFO
134 FILEVERSION 1,0,0,3
135 PRODUCTVERSION 1,0,0,3
136 FILEFLAGSMASK 0x3fL
137#ifdef _DEBUG
138 FILEFLAGS 0x1L
139#else
140 FILEFLAGS 0x0L
141#endif
142 FILEOS 0x40004L
143 FILETYPE 0x1L
144 FILESUBTYPE 0x0L
145BEGIN
146 BLOCK "StringFileInfo"
147 BEGIN
148 BLOCK "040904b0"
149 BEGIN
150 VALUE "CompanyName", "Klever Group (http://www.klever.net/)\0"
151 VALUE "FileDescription", "INSTALL: KINSole, telnet client\0"
152 VALUE "FileVersion", "1, 0, 0, 3\0"
153 VALUE "InternalName", "INSTALL\0"
154 VALUE "LegalCopyright", "Copyright © 1998, 2002 Klever Group (http://www.klever.net/)\0"
155 VALUE "LegalTrademarks", "Klever Group (http://www.klever.net/)\0"
156 VALUE "OriginalFilename", "INSTALL.EXE\0"
157 VALUE "ProductName", "KINSole\0"
158 VALUE "ProductVersion", "1, 0, 0, 3\0"
159 END
160 END
161 BLOCK "VarFileInfo"
162 BEGIN
163 VALUE "Translation", 0x409, 1200
164 END
165END
166
167#endif // !_MAC
168
169#endif // English (U.S.) resources
170/////////////////////////////////////////////////////////////////////////////
171
172
173
174#ifndef APSTUDIO_INVOKED
175/////////////////////////////////////////////////////////////////////////////
176//
177// Generated from the TEXTINCLUDE 3 resource.
178//
179#include "custom.rch"
180/////////////////////////////////////////////////////////////////////////////
181#endif // not APSTUDIO_INVOKED
182
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 @@
1//{{NO_DEPENDENCIES}}
2// Microsoft Developer Studio generated include file.
3// Used by Install.rc
4//
5#define IDD_INSTALLING 101
6#define IDD_PATH 102
7#define IDI_ICON 105
8#define IDC_DISKS 1000
9#define IDC_STATE 1001
10#define IDC_PROGRESS 1002
11#define IDC_PROMPT 1003
12#define IDC_PATH 1004
13#define IDC_BROWSE 1005
14
15// Next default values for new objects
16//
17#ifdef APSTUDIO_INVOKED
18#ifndef APSTUDIO_READONLY_SYMBOLS
19#define _APS_NEXT_RESOURCE_VALUE 107
20#define _APS_NEXT_COMMAND_VALUE 40001
21#define _APS_NEXT_CONTROL_VALUE 1006
22#define _APS_NEXT_SYMED_VALUE 101
23#endif
24#endif
diff --git a/kinsole.cpp b/kinsole.cpp
new file mode 100644
index 0000000..463db1c
--- a/dev/null
+++ b/kinsole.cpp
@@ -0,0 +1,736 @@
1#include <stdio.h>
2
3 #ifdef_DEBUG
4#include <afxwin.h>
5#else
6#define ASSERT(f) ((void)0)
7#define VERIFY(f) ((void)(f))
8#define TRACE0(sz)
9#define TRACE1(sz, p1)
10#define TRACE2(sz, p1, p2)
11#define TRACE3(sz, p1, p2, p3)
12#endif
13
14#include <winsock.h>
15#include "resource.h"
16#include "windowsx.h"
17
18 #define DAMN_KIN_NAME "KINSole"
19 #define DAMN_KIN_VERSION"v1.00 Beta 3"
20
21#ifdef _DEBUG
22#define new DEBUG_NEW
23#undef THIS_FILE
24static char THIS_FILE[] = __FILE__;
25#endif
26
27enum {
28 WM_USERSOCKET = WM_USER+16,
29 WM_USERKEY,
30 WM_USERNOP
31};
32enum {
33 tnIAC = 255,
34 tnSE = 240,
35 tnNOP = 241,
36 tnDM = 242,
37 tnBreak = 243,
38 tnIP = 244,
39 tnAO = 245,
40 tnAYT = 246,
41 tnEC = 247,
42 tnEL = 248,
43 tnGA = 249,
44 tnSB = 250,
45 tnWILL = 251,
46 tnWONT = 252,
47 tnDO = 253,
48 tnDONT = 254
49};
50
51WSADATA wsaData;
52ATOM wsaWC = NULL;
53HWND wsaW = NULL;
54
55CHAR remoteHost[256];
56CHAR remoteProt[256];
57sockaddr_in remoteSIN;
58
59
60SOCKET telnetSocket;
61HANDLE hConsoleInput;
62HANDLE hConsoleOutput;
63HWND hConsoleWindow;
64HANDLE hConsoleThread;
65DWORD consoleThreadID;
66HANDLE hDispatchThread;
67DWORD dispatchThreadID;
68BOOL bTelnet,bTermPulled;
69
70 enum_cState {
71 cstateNone = 0, cstateIAC, cstateDO, cstateSB, cstateSBData,
72 cstateSBDataIAC, cstateWILL, cstateDONT,cstateWONT,
73 }connState = cstateNone;
74BYTE negOption = 0;
75
76
77BOOL SelectSocket() {
78 return WSAAsyncSelect(telnetSocket,wsaW,WM_USERSOCKET,FD_READ|FD_OOB|FD_CLOSE)!=SOCKET_ERROR;
79}
80
81BOOL ShowWill(BYTE o)
82{
83 TRACE1("We're WILLing to %d\n",(WORD)o);
84static
85BYTE d[3] = {tnIAC,tnWILL,0};
86 d[2] = o;
87BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d);
88 SelectSocket();
89 return rv;
90}
91BOOL ShowUnwill(BYTE o)
92{
93 TRACE1("We're NOT WILLing to %d\n",(WORD)o);
94static
95BYTE d[3] = {tnIAC,tnWONT,0};
96 d[2] = o;
97BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d);
98 SelectSocket();
99 return rv;
100}
101BOOL BegDo(BYTE o)
102{
103 TRACE1("We beg to DO %d\n",(WORD)o);
104static
105BYTE d[3] = {tnIAC,tnDO,0};
106 d[2] = o;
107BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d);
108 SelectSocket();
109 return rv;
110}
111BOOL BegDont(BYTE o)
112{
113 TRACE1("We beg DONT'T %d\n",(WORD)o);
114static
115BYTE d[3] = {tnIAC,tnDONT,0};
116 d[2] = o;
117BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d);
118 SelectSocket();
119 return rv;
120}
121BOOL SubNegotiate(BYTE o,LPBYTE data,UINT size)
122{
123LPBYTE d = new BYTE[3+size*2+2];
124int ds = 0;
125 d[ds++]=tnIAC; d[ds++]=tnSB; d[ds++]=o;
126 for(UINT tmp=0;tmp<size;tmp++)
127 if(data[tmp]!=tnIAC)
128 d[ds++]=data[tmp];
129 else{
130 d[ds++]=tnIAC; d[ds++]=tnIAC;
131 }
132 d[ds++]=tnIAC;d[ds++]=tnSE;
133BOOL rv = send(telnetSocket,(char*)d,ds,0)==ds;
134 delete d;
135 SelectSocket();
136 return rv;
137}
138BOOL SendLiteral(CHAR c)
139{
140BYTE d[2] = {tnIAC,0};
141BOOL rv = FALSE;
142 if(c==tnIAC){
143 d[1]=c;
144 rv = send(telnetSocket,(char*)d,2,0)==2;
145 }else
146 rv = send(telnetSocket,&c,1,0)==1;
147 return rv;
148}
149BOOL SendLiteral(LPCTSTR c,UINT size)
150{
151 for(UINT tmp=0;tmp<size;tmp++)
152 SendLiteral(c[tmp]);
153 return TRUE;
154}
155BOOL SendLiteral(LPCTSTR c)
156{
157 return SendLiteral(c,strlen(c));
158}
159BOOL SendCommand(BYTE c)
160{
161 TRACE1("Issuing %d command\n",(WORD)c);
162static
163BYTE d[2] = {tnIAC,0};
164 d[1] = c;
165BOOL rv = send(telnetSocket,(char*)d,sizeof(d),0)==sizeof(d);
166 SelectSocket();
167 return rv;
168
169}
170
171BOOL CALLBACK consoleCtrlHandler(DWORD dwCtrlType)
172{
173 switch(dwCtrlType){
174 case CTRL_BREAK_EVENT:
175 SendCommand(tnIP);
176 return TRUE;
177 case CTRL_CLOSE_EVENT:
178 case CTRL_LOGOFF_EVENT:
179 case CTRL_SHUTDOWN_EVENT:
180 PostMessage(wsaW,WM_QUIT,0,0);
181 return TRUE;
182 }
183 return FALSE;
184}
185
186#include "options.cpp"
187
188BOOL ProcessConsoleInput()
189{
190INPUT_RECORD ir[512];
191DWORD got;
192 while(GetNumberOfConsoleInputEvents(hConsoleInput,&got) && got){
193 VERIFY(ReadConsoleInput(hConsoleInput,ir,(sizeof(ir)/sizeof(*ir)),&got));
194 for(DWORD tmp=0;tmp<got;tmp++){
195 if(ir[tmp].EventType==KEY_EVENT && ir[tmp].Event.KeyEvent.bKeyDown){
196 if((
197 ir[tmp].Event.KeyEvent.wVirtualKeyCode=='X' ||
198 ir[tmp].Event.KeyEvent.wVirtualKeyCode=='Q'
199 ) && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)
200 ){
201 PostMessage(wsaW,WM_QUIT,0,0);
202 return FALSE;
203 }else if(
204 ir[tmp].Event.KeyEvent.wVirtualKeyCode=='O'
205 && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)
206 ){
207 SendCommand(tnAO);
208 }else if(
209 ir[tmp].Event.KeyEvent.wVirtualKeyCode=='Y'
210 && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)
211 ){
212 SendCommand(tnAYT);
213 }else if(
214 ir[tmp].Event.KeyEvent.wVirtualKeyCode=='T'
215 && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)
216 ){
217 BegDo(toTimingMark);
218 }else if(
219 ir[tmp].Event.KeyEvent.wVirtualKeyCode==VK_INSERT
220 && ir[tmp].Event.KeyEvent.dwControlKeyState&SHIFT_PRESSED
221 ){
222 if(IsClipboardFormatAvailable(CF_OEMTEXT)){
223 ASSERT(wsaW);
224 if(OpenClipboard(wsaW)){
225 HANDLE h = GetClipboardData(CF_OEMTEXT);
226 LPVOID gl = GlobalLock(h);
227 TerminalIn((LPCTSTR)gl);
228 GlobalUnlock(h);
229 // GlobalFree(h);
230 CloseClipboard();
231 }
232 }
233 }else if(
234 ir[tmp].Event.KeyEvent.wVirtualKeyCode==VK_INSERT
235 && ir[tmp].Event.KeyEvent.dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)
236 ){
237 if(hConsoleWindow)
238 SendNotifyMessage(hConsoleWindow,WM_COMMAND,MAKELONG(0xE003,0),NULL);
239 }else
240 TerminalIn(ir[tmp].Event.KeyEvent);
241 }
242 }
243 }
244
245 return TRUE;
246}
247
248ULONG CALLBACK ConsoleThreadProc(LPVOID)
249{
250 for(;;){
251 DWORD eves;
252 if(!(GetNumberOfConsoleInputEvents(hConsoleInput,&eves) && eves))
253 WaitForSingleObject(hConsoleInput,INFINITE);
254 ASSERT(wsaW);
255 SendMessage(wsaW,WM_USERKEY,0,0);
256 }
257 return 0;
258}
259
260BOOL SINTelnet(sockaddr_in& sin)
261{
262protoent* pe = getprotobyname("tcp");
263short proto = pe?pe->p_proto:6;
264 telnetSocket = socket(sin.sin_family,SOCK_STREAM,proto);
265 if(telnetSocket==INVALID_SOCKET){
266 printf("Failed to create socket\n");
267 return FALSE;
268 }
269static
270BOOL bOOBInline = FALSE;
271 if(setsockopt(telnetSocket,SOL_SOCKET,SO_OOBINLINE,(const char*)&bOOBInline,sizeof(bOOBInline))){
272 TRACE0("Failed to setsockopt for OOB data\n");
273 }
274 printf("Trying %s..",inet_ntoa(sin.sin_addr));
275 if(connect(telnetSocket,(sockaddr*)&sin,sizeof(sin))){
276 switch(WSAGetLastError()){
277 case WSAECONNREFUSED: printf("\nConnection refused\n"); break;
278 case WSAEHOSTUNREACH: printf("\nNo route to host\n"); break;
279 case WSAENETDOWN: printf("\nNetwork is down\n"); break;
280 case WSAENETUNREACH: printf("\nNetwork is unreachable\n"); break;
281 case WSAETIMEDOUT: printf("\nConnection timed out\n"); break;
282 default: printf("\nFailed to connect\n"); break;
283 }
284 return FALSE;
285 }
286 printf("\nConnected. Alt-X/Alt-Q - Close telnet connection\n");
287 //***hConsoleInput = ::GetStdHandle(STD_INPUT_HANDLE);
288 //***hConsoleOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
289 hConsoleInput = CreateFile("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
290 NULL,OPEN_EXISTING,0,NULL);
291 hConsoleOutput = CreateFile("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
292 NULL,OPEN_EXISTING,0,NULL);
293 ASSERT(hConsoleInput!=INVALID_HANDLE_VALUE &&
294 hConsoleOutput!=INVALID_HANDLE_VALUE);
295 if(!(bTelnet || bTermPulled))
296 TerminalPullType("TTY");
297 InitOptionsTable();
298 TRACE0("Connected\n");
299 VERIFY(SetConsoleCtrlHandler(&consoleCtrlHandler,TRUE));
300 hConsoleThread = CreateThread(NULL,0,ConsoleThreadProc,NULL,0,&consoleThreadID);
301 ASSERT(hConsoleThread);
302 if(bTelnet){
303 AskDo(toSuppressGA);
304 AskWill(toTerminalType);
305 AskWill(toNAWS);
306 AskUnwill(toEcho);
307 AskDo(toEcho);
308 if(Envars && nEnvars)
309 AskWill(toNewEnviron);// *** Or better (what's better?)
310 //AskWill(toLineMode);
311 // *** STATUS
312 }
313MSG msg;
314int rvgm;
315 PostMessage(wsaW,WM_USERNOP,0,0);
316 VERIFY(SelectSocket());
317 while(rvgm=GetMessage(&msg,NULL,NULL,NULL)){
318 if(rvgm<0)
319 break;// Some wheeping needed
320 TranslateMessage(&msg);
321 DispatchMessage(&msg);
322 //LRESULT CALLBACK WSWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
323 // WSWndProc(msg.hwnd,msg.message,msg.wParam,msg.lParam);
324 VERIFY(SelectSocket());
325 }
326 VERIFY(TerminateThread(hConsoleThread,0xFFFFFFFF));
327 VERIFY(SetConsoleCtrlHandler(&consoleCtrlHandler,FALSE));
328 closesocket(telnetSocket);
329 return TRUE;
330}
331
332BOOL Telnet(LPCTSTR hostName,UINT port)
333{
334 memset(&remoteSIN,0,sizeof(remoteSIN));
335 remoteSIN.sin_family = AF_INET;
336 remoteSIN.sin_port = htons(port);
337
338 remoteSIN.sin_addr.s_addr = inet_addr(hostName);
339 if(remoteSIN.sin_addr.s_addr==INADDR_NONE){
340 hostent* he = gethostbyname(hostName);
341 if(!he){
342 printf("Failed to resolve host name\n");
343 return FALSE;
344 }
345 ASSERT(he->h_addrtype==AF_INET);
346 ASSERT(he->h_length==sizeof(remoteSIN.sin_addr));
347 memmove(&remoteSIN.sin_addr,*he->h_addr_list,sizeof(remoteSIN.sin_addr));
348 }
349 strcpy(remoteHost,hostName);
350 return SINTelnet(remoteSIN);
351}
352
353
354void ProcessIACByte(BYTE c)
355{
356 connState = cstateNone;
357 switch(c){
358 case tnIAC:
359 TerminalOut(c);
360 break;
361 case tnSE:
362 TRACE0("SE\n");break;
363 case tnNOP:
364 TRACE0("NOP\n");break;
365 case tnDM:
366 TRACE0("DM\n");break;
367 case tnBreak:
368 TRACE0("Break\n");break;
369 case tnIP:
370 TRACE0("IP\n");break;
371 case tnAO:
372 TRACE0("AO\n");break;
373 case tnAYT:
374 TRACE0("AYT\n");break;
375 case tnEC:
376 TRACE0("EC\n");break;
377 case tnEL:
378 TRACE0("EL\n");break;
379 case tnGA:
380 TRACE0("GA\n");break;
381 case tnSB:
382 connState = cstateSB;
383 break;
384 case tnWILL:
385 connState = cstateWILL;
386 break;
387 case tnWONT:
388 connState = cstateWONT;
389 break;
390 case tnDO:
391 connState = cstateDO;
392 break;
393 case tnDONT:
394 connState = cstateDONT;
395 break;
396 default:
397 TRACE1("Unknown OpCode = %d\n",(WORD)c);
398 break;
399 }
400}
401
402void ProcessNetByte(BYTE c)
403{
404 //TRACE1("<%d>",connState);
405 switch(connState){
406 case cstateWONT:
407 ProcessWONT(c);
408 break;
409 case cstateDO:
410 ProcessDO(c);
411 break;
412 case cstateWILL:
413 ProcessWILL(c);
414 break;
415 case cstateDONT:
416 ProcessDONT(c);
417 break;
418 case cstateSB:
419 negOption = c;
420 connState = cstateSBData;
421 break;
422 case cstateSBData:
423 case cstateSBDataIAC:
424 ProcessSBData(c);
425 break;
426 case cstateIAC:
427 ProcessIACByte(c);
428 break;
429 case cstateNone:
430 default:
431 ASSERT(connState==cstateNone);
432 if(c==tnIAC)
433 connState=cstateIAC;
434 else
435 TerminalOut(c);
436 break;
437 }
438}
439
440LRESULT WSMessage(WPARAM wP,LPARAM lP)
441{
442 if(WSAGETSELECTERROR(lP)){
443 TRACE0("SelectError\n");
444 PostMessage(wsaW,WM_QUIT,0,0);
445 return 0;
446 }
447 if(WSAGETSELECTEVENT(lP)&FD_READ){
448 //?? TRACE0("FD_READ\n");
449 BYTE input[80*12];
450 int got;
451 TerminalPreO();
452 //?? TRACE0("rv\n");
453 got=recv(telnetSocket,(CHAR*)input,sizeof(input),0);
454 //?? TRACE1("/rv %d\n",got);
455 for(int tmp=0;tmp<got;tmp++)
456 ProcessNetByte(input[tmp]);
457 TerminalPostO();
458 //?? TRACE0("/FD_READ\n");
459 return 0;
460 }
461 if(WSAGETSELECTEVENT(lP)&FD_OOB){
462 TRACE0("OOB\n");
463 }
464 if(WSAGETSELECTEVENT(lP)&FD_CLOSE){
465 TRACE0("CLOSE\n");
466 PostMessage(wsaW,WM_QUIT,0,0);
467 return 0;
468 }
469 VERIFY(SelectSocket());
470 return 0;
471}
472
473LRESULT CALLBACK WSWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
474{
475 switch(uMsg){
476 case WM_USERSOCKET:
477 return WSMessage(wParam,lParam);
478 case WM_USERKEY:
479 return ProcessConsoleInput();
480 default:
481 TRACE0("DEFWINDOWPROC\n");
482 return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
483 }
484 return 0;
485}
486
487
488BOOL InitializeWinsock()
489{
490 if(WSAStartup(0x101,&wsaData)){
491 printf("Failed to initialize winsock services\n");
492 return FALSE;
493 }
494WNDCLASS wc;
495 memset(&wc,0,sizeof(wc));
496 wc.lpfnWndProc=WSWndProc; wc.hInstance=::GetModuleHandle(NULL);
497 wc.lpszClassName = "_WSTFWC_";
498 wsaWC = RegisterClass(&wc);
499 if(!wsaWC){
500 printf("Failed to initialize winsock services - 1\n");
501 return FALSE;
502 }
503 wsaW = ::CreateWindow("_WSTFWC_","KIN Sole Mio",0,0,0,0,0,NULL,NULL,::GetModuleHandle(NULL),NULL);
504 if(!wsaW){
505 printf("Failed to initialize winsock services\n");
506 return FALSE;
507 }
508 return TRUE;
509}
510void DeinitializeWinsock()
511{
512 if(wsaW)
513 ::DestroyWindow(wsaW);
514 wsaW=NULL;
515 if(wsaWC)
516 ::UnregisterClass("_WSTFWC_",::GetModuleHandle(NULL));
517 wsaWC=NULL;
518 WSACleanup();
519}
520
521HWND GetThisConsoleWnd()
522{
523DWORD pid = GetCurrentProcessId();
524CHAR title[512];
525CHAR* t = title;
526 if(!GetConsoleTitle(title,sizeof(title)))
527 t = NULL;
528HWND hrv = FindWindowEx(NULL,NULL,"tty",t);
529HWND nopro = NULL;
530UINT nopros=0;
531 do{
532 DWORD wpid;
533 if(!GetWindowThreadProcessId(hrv,&wpid))
534 continue;
535 if(wpid==pid)
536 return hrv;
537 nopro=hrv;
538 nopros++;
539 hrv = FindWindowEx(NULL,hrv,"tty",t);
540 }while(hrv);
541 if(nopros==1){
542 ASSERT(nopro);
543 return nopro;
544 }
545 return NULL;
546}
547
548main(int argc,char*argv[])
549{
550 if(argc<2){
551usagebye:
552 printf(
553 DAMN_KIN_NAME " " DAMN_KIN_VERSION ", Copyright (c) 1998, 2002 Klever Group (http://www.klever.net/)\n\n"
554 "Usage:\t" DAMN_KIN_NAME " [<options> ]<host-name/ip-address>[ <port>]\n\n"
555 "Options are:\n"
556 "-r## or -##\tSet number of rows in console screenbuffer\n"
557 "-c##\t\tSet number of columns in console screenbuffer\n"
558 "\tnote: changing console screenbuffer size may not work properly\n"
559 "\twhen in full-screen mode\n"
560 "-l<user>\tPass username to remote server in environment\n"
561 "-e<var>=<val>\tPass environment variable to remote server\n"
562 "-v<var>=<val>\tPass user environment variable to remote server\n"
563 "-t<termtype>\tChange preferred terminal type\n"
564 "\tnote: there are only two different terminal emulations in this\n"
565 "\tbeta release - one for dumb terminal and one for vt terminal\n"
566 );
567 CleanEnvars();
568 return 1;
569 }
570 if(!InitializeWinsock()){
571 DeinitializeWinsock();
572 return 2;
573 }
574CONSOLE_SCREEN_BUFFER_INFO csbi;
575int ac = 0;
576CHAR *ho = NULL, *po = NULL;
577HANDLE hConsole = CreateFile("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
578 NULL,OPEN_EXISTING,0,NULL);
579 ASSERT(hConsole);
580 // *** GetStdHandle(STD_OUTPUT_HANDLE);// *?*?* Do something about redirections and not only here.
581 VERIFY(GetConsoleScreenBufferInfo(hConsole,&csbi));
582BOOL bSized=FALSE;
583 bTermPulled=FALSE;
584 for(int tmp=1;tmp<argc;tmp++){
585 char* v = argv[tmp];
586 ASSERT(v && *v);
587 if((*v)=='/' || (*v)=='-'){
588 int lines = atoi(&v[1]);
589 if(lines){
590 if(lines<csbi.dwSize.Y){
591 SMALL_RECT wi = {0,0,csbi.dwSize.X-1,lines-1};
592 VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi));
593 }
594 COORD ns = {csbi.dwSize.X,lines};
595 if(SetConsoleScreenBufferSize(hConsole,ns))
596 bSized=TRUE;
597 }else if(v[1]=='r'){
598 int lines = atoi(&v[2]);
599 if(lines){
600 if(lines<csbi.dwSize.Y){
601 SMALL_RECT wi = {0,0,csbi.dwSize.X-1,lines-1};
602 VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi));
603 }
604 COORD ns = {csbi.dwSize.X,lines};
605 if(SetConsoleScreenBufferSize(hConsole,ns))
606 bSized=TRUE;
607 }else
608 goto usagebye;
609 }else if(v[1]=='c'){
610 int rows = atoi(&v[2]);
611 if(rows){
612 if(rows<csbi.dwSize.X){
613 SMALL_RECT wi = {0,0,rows-1,csbi.dwSize.Y-1};
614 VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi));
615 }
616 COORD ns = {rows,csbi.dwSize.Y};
617 if(SetConsoleScreenBufferSize(hConsole,ns))
618 bSized=TRUE;
619 }else
620 goto usagebye;
621 }else if(v[1]=='l'){
622 CHAR* vv = &v[2];
623 VERIFY(AddEnvar(nesbVar,"USER",vv));
624 }else if(v[1]=='e'){ // -e<name>=<value>VAR
625 CHAR* n = &v[2];
626 CHAR* vv = strchr(&v[2],'=');
627 if(!vv)
628 goto usagebye;
629 *(vv++)=0;
630 VERIFY(AddEnvar(nesbVar,n,vv));
631 }else if(v[1]=='v'){ // -v<name>=<value>USERVAR
632 CHAR* n = &v[2];
633 CHAR* vv = strchr(n,'=');
634 if(!vv)
635 goto usagebye;
636 *(vv++)=0;
637 VERIFY(AddEnvar(nesbUserVar,n,vv));
638 }else if(v[1]=='t'){// -t<ttype> -t<tname>=<ttype>
639 CHAR* n = &v[2];
640 CHAR* nn = strchr(n,'=');
641 if(nn){
642 *(nn++)=0;
643 if(!*nn)
644 nn=NULL;
645 }
646 if(!TerminalPullType(nn?nn:n,nn?n:NULL)){
647 printf("Available terminal types are:");
648 TerminalPrintTypes();
649 printf("\n");
650 goto usagebye;
651 }
652 bTermPulled=TRUE;
653 }else if(v[1]=='#'){
654 int cp = atoi(&v[2]);
655 #ifdef_DEBUG
656 TRACE2("SetCP(%d)=%d\n",cp,SetConsoleCP(cp));
657 TRACE2("SetOutCP(%d)=%d\n",cp,SetConsoleOutputCP(cp));
658#else
659 SetConsoleCP(cp);
660 SetConsoleOutputCP(cp);
661#endif
662 TRACE2("CP,OCP=%d,%d\n",GetConsoleCP(),GetConsoleOutputCP());
663 }else
664 goto usagebye;
665 }else{
666 if(ac==0){
667 ho = v;
668 ac++;
669 }else if(ac==1){
670 po = v;
671 ac++;
672 }else
673 goto usagebye;
674 }
675 }
676 if(!ho)
677 goto usagebye;
678servent* se = getservbyname("telnet","tcp");
679UINT port = po?atol(po):(se?ntohs(se->s_port):23);
680 if(port==23 || (se && port==ntohs(se->s_port)))
681 bTelnet = TRUE;
682 if(po && !port){
683 se = getservbyname(po,"tcp");
684 if(!se){
685 printf("Failed to resolve tcp-service port name\n");
686 DeinitializeWinsock();
687 return 2;
688 }
689 port = ntohs(se->s_port);
690 if(!stricmp(po,"telnet"))
691 bTelnet = TRUE;
692 else
693 bTelnet = FALSE;
694 }else{
695 se = getservbyport(htons(port),"tcp");
696 if(se){
697 po = se->s_name;
698 if(!stricmp(po,"telnet"))
699 bTelnet=TRUE;
700 }else{
701 VERIFY(_itoa(port,remoteProt,10));
702 po = NULL;
703 bTelnet=FALSE;
704 }
705 }
706 if(po)
707 strcpy(remoteProt,po);
708HICON hIcon = LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_IKON));
709LONG oldBIcon = NULL, oldSIcon = NULL;
710 hConsoleWindow = GetThisConsoleWnd();
711 if(hConsoleWindow){
712 oldBIcon = SendMessage(hConsoleWindow,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
713 oldSIcon = SendMessage(hConsoleWindow,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
714 }
715 Telnet(ho,port);
716 CleanEnvars();
717 if(hConsoleWindow){
718 SendMessage(hConsoleWindow,WM_SETICON,ICON_BIG,(LPARAM)oldBIcon);
719 SendMessage(hConsoleWindow,WM_SETICON,ICON_SMALL,(LPARAM)oldSIcon);
720 }
721 Sleep(150);
722 if(bSized){
723 CONSOLE_SCREEN_BUFFER_INFO CSBI;
724 VERIFY(GetConsoleScreenBufferInfo(hConsole,&CSBI));
725 if(CSBI.dwSize.Y>csbi.dwSize.Y || CSBI.dwSize.X>csbi.dwSize.X){
726 SMALL_RECT wi = {0,0,csbi.dwSize.X-1,csbi.dwSize.Y-1};
727 VERIFY(SetConsoleWindowInfo(hConsole,TRUE,&wi));
728 }
729 COORD ns = {csbi.dwSize.X,csbi.dwSize.Y};
730 VERIFY(SetConsoleScreenBufferSize(hConsole,ns));
731 }
732 Sleep(100);
733 DeinitializeWinsock();
734 Sleep(100);
735 return 0;
736}
diff --git a/kinsole.mak b/kinsole.mak
new file mode 100644
index 0000000..b25a32d
--- a/dev/null
+++ b/kinsole.mak
@@ -0,0 +1,612 @@
1# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
2# ** DO NOT EDIT **
3
4# TARGTYPE "Win32 (x86) Application" 0x0101
5# TARGTYPE "Win32 (x86) Console Application" 0x0103
6
7!IF "$(CFG)" == ""
8CFG=Install - Win32 Debug
9!MESSAGE No configuration specified. Defaulting to Install - Win32 Debug.
10!ENDIF
11
12!IF "$(CFG)" != "KINSole - Win32 Release" && "$(CFG)" !=\
13 "KINSole - Win32 Debug" && "$(CFG)" != "Install - Win32 Release" && "$(CFG)" !=\
14 "Install - Win32 Debug"
15!MESSAGE Invalid configuration "$(CFG)" specified.
16!MESSAGE You can specify a configuration when running NMAKE on this makefile
17!MESSAGE by defining the macro CFG on the command line. For example:
18!MESSAGE
19!MESSAGE NMAKE /f "kinsole.mak" CFG="Install - Win32 Debug"
20!MESSAGE
21!MESSAGE Possible choices for configuration are:
22!MESSAGE
23!MESSAGE "KINSole - Win32 Release" (based on "Win32 (x86) Console Application")
24!MESSAGE "KINSole - Win32 Debug" (based on "Win32 (x86) Console Application")
25!MESSAGE "Install - Win32 Release" (based on "Win32 (x86) Application")
26!MESSAGE "Install - Win32 Debug" (based on "Win32 (x86) Application")
27!MESSAGE
28!ERROR An invalid configuration is specified.
29!ENDIF
30
31!IF "$(OS)" == "Windows_NT"
32NULL=
33!ELSE
34NULL=nul
35!ENDIF
36################################################################################
37# Begin Project
38# PROP Target_Last_Scanned "Install - Win32 Debug"
39
40!IF "$(CFG)" == "KINSole - Win32 Release"
41
42# PROP BASE Use_MFC 0
43# PROP BASE Use_Debug_Libraries 0
44# PROP BASE Output_Dir "Release"
45# PROP BASE Intermediate_Dir "Release"
46# PROP BASE Target_Dir ""
47# PROP Use_MFC 0
48# PROP Use_Debug_Libraries 0
49# PROP Output_Dir "Release"
50# PROP Intermediate_Dir "Release"
51# PROP Target_Dir ""
52OUTDIR=.\Release
53INTDIR=.\Release
54# Begin Custom Macros
55OutDir=.\Release
56TargetName=kinsole
57# End Custom Macros
58
59ALL : "$(OUTDIR)\kinsole.exe" "$(OUTDIR)\kinsole.ex_" "$(OUTDIR)\kinsole.hlp"\
60 "$(OUTDIR)\kinsole.cnt" "$(OUTDIR)\kinsole.hl_" "$(OUTDIR)\kinsole.cn_"
61
62CLEAN :
63 -@erase "$(INTDIR)\kinsole.cn_"
64 -@erase "$(INTDIR)\kinsole.cnt"
65 -@erase "$(INTDIR)\kinsole.hl_"
66 -@erase "$(INTDIR)\kinsole.hlp"
67 -@erase "$(INTDIR)\KINSole.obj"
68 -@erase "$(INTDIR)\KINSole.res"
69 -@erase "$(OUTDIR)\kinsole.ex_"
70 -@erase "$(OUTDIR)\kinsole.exe"
71 -@erase "$(OUTDIR)\kinsole.map"
72
73"$(OUTDIR)" :
74 if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
75
76CPP=cl.exe
77# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
78# ADD CPP /nologo /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c
79# SUBTRACT CPP /YX
80CPP_PROJ=/nologo /ML /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
81 /Fo"$(INTDIR)/" /c
82CPP_OBJS=.\Release/
83CPP_SBRS=.\.
84
85.c{$(CPP_OBJS)}.obj:
86 $(CPP) $(CPP_PROJ) $<
87
88.cpp{$(CPP_OBJS)}.obj:
89 $(CPP) $(CPP_PROJ) $<
90
91.cxx{$(CPP_OBJS)}.obj:
92 $(CPP) $(CPP_PROJ) $<
93
94.c{$(CPP_SBRS)}.sbr:
95 $(CPP) $(CPP_PROJ) $<
96
97.cpp{$(CPP_SBRS)}.sbr:
98 $(CPP) $(CPP_PROJ) $<
99
100.cxx{$(CPP_SBRS)}.sbr:
101 $(CPP) $(CPP_PROJ) $<
102
103RSC=rc.exe
104# ADD BASE RSC /l 0x409 /d "NDEBUG"
105# ADD RSC /l 0x409 /d "NDEBUG"
106RSC_PROJ=/l 0x409 /fo"$(INTDIR)/KINSole.res" /d "NDEBUG"
107BSC32=bscmake.exe
108# ADD BASE BSC32 /nologo
109# ADD BSC32 /nologo
110BSC32_FLAGS=/nologo /o"$(OUTDIR)/kinsole.bsc"
111BSC32_SBRS= \
112
113LINK32=link.exe
114# ADD BASE 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 /nologo /subsystem:console /machine:I386
115# 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 wsock32.lib /nologo /subsystem:console /map /machine:I386
116LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
117 advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
118 odbccp32.lib wsock32.lib /nologo /subsystem:console /incremental:no\
119 /pdb:"$(OUTDIR)/kinsole.pdb" /map:"$(INTDIR)/kinsole.map" /machine:I386\
120 /out:"$(OUTDIR)/kinsole.exe"
121LINK32_OBJS= \
122 "$(INTDIR)\KINSole.obj" \
123 "$(INTDIR)\KINSole.res"
124
125"$(OUTDIR)\kinsole.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
126 $(LINK32) @<<
127 $(LINK32_FLAGS) $(LINK32_OBJS)
128<<
129
130# Begin Custom Build - Performing Custom Build Step
131OutDir=.\Release
132TargetName=kinsole
133InputPath=.\Release\kinsole.exe
134SOURCE=$(InputPath)
135
136"$(OutDir)\$(TargetName).ex_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
137 compress $(OutDir)\$(TargetName).exe $(OutDir)\$(TargetName).ex_
138
139# End Custom Build
140
141!ELSEIF "$(CFG)" == "KINSole - Win32 Debug"
142
143# PROP BASE Use_MFC 0
144# PROP BASE Use_Debug_Libraries 1
145# PROP BASE Output_Dir "Debug"
146# PROP BASE Intermediate_Dir "Debug"
147# PROP BASE Target_Dir ""
148# PROP Use_MFC 2
149# PROP Use_Debug_Libraries 1
150# PROP Output_Dir "Debug"
151# PROP Intermediate_Dir "Debug"
152# PROP Target_Dir ""
153OUTDIR=.\Debug
154INTDIR=.\Debug
155# Begin Custom Macros
156OutDir=.\Debug
157TargetName=kinsole
158# End Custom Macros
159
160ALL : "$(OUTDIR)\kinsole.exe" "$(OUTDIR)\kinsole.ex_" "$(OUTDIR)\kinsole.hlp"\
161 "$(OUTDIR)\kinsole.cnt" "$(OUTDIR)\kinsole.hl_" "$(OUTDIR)\kinsole.cn_"
162
163CLEAN :
164 -@erase "$(INTDIR)\kinsole.cn_"
165 -@erase "$(INTDIR)\kinsole.cnt"
166 -@erase "$(INTDIR)\kinsole.hl_"
167 -@erase "$(INTDIR)\kinsole.hlp"
168 -@erase "$(INTDIR)\KINSole.obj"
169 -@erase "$(INTDIR)\KINSole.res"
170 -@erase "$(INTDIR)\vc40.idb"
171 -@erase "$(INTDIR)\vc40.pdb"
172 -@erase "$(OUTDIR)\kinsole.ex_"
173 -@erase "$(OUTDIR)\kinsole.exe"
174 -@erase "$(OUTDIR)\kinsole.ilk"
175 -@erase "$(OUTDIR)\kinsole.pdb"
176
177"$(OUTDIR)" :
178 if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
179
180CPP=cl.exe
181# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
182# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_AFXDLL" /D "_MBCS" /c
183# SUBTRACT CPP /YX
184CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
185 /D "_AFXDLL" /D "_MBCS" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
186CPP_OBJS=.\Debug/
187CPP_SBRS=.\.
188
189.c{$(CPP_OBJS)}.obj:
190 $(CPP) $(CPP_PROJ) $<
191
192.cpp{$(CPP_OBJS)}.obj:
193 $(CPP) $(CPP_PROJ) $<
194
195.cxx{$(CPP_OBJS)}.obj:
196 $(CPP) $(CPP_PROJ) $<
197
198.c{$(CPP_SBRS)}.sbr:
199 $(CPP) $(CPP_PROJ) $<
200
201.cpp{$(CPP_SBRS)}.sbr:
202 $(CPP) $(CPP_PROJ) $<
203
204.cxx{$(CPP_SBRS)}.sbr:
205 $(CPP) $(CPP_PROJ) $<
206
207RSC=rc.exe
208# ADD BASE RSC /l 0x409 /d "_DEBUG"
209# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
210RSC_PROJ=/l 0x409 /fo"$(INTDIR)/KINSole.res" /d "_DEBUG" /d "_AFXDLL"
211BSC32=bscmake.exe
212# ADD BASE BSC32 /nologo
213# ADD BSC32 /nologo
214BSC32_FLAGS=/nologo /o"$(OUTDIR)/kinsole.bsc"
215BSC32_SBRS= \
216
217LINK32=link.exe
218# ADD BASE 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 /nologo /subsystem:console /debug /machine:I386
219# ADD LINK32 wsock32.lib /nologo /subsystem:console /debug /machine:I386
220LINK32_FLAGS=wsock32.lib /nologo /subsystem:console /incremental:yes\
221 /pdb:"$(OUTDIR)/kinsole.pdb" /debug /machine:I386 /out:"$(OUTDIR)/kinsole.exe"
222LINK32_OBJS= \
223 "$(INTDIR)\KINSole.obj" \
224 "$(INTDIR)\KINSole.res"
225
226"$(OUTDIR)\kinsole.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
227 $(LINK32) @<<
228 $(LINK32_FLAGS) $(LINK32_OBJS)
229<<
230
231# Begin Custom Build
232OutDir=.\Debug
233TargetName=kinsole
234InputPath=.\Debug\kinsole.exe
235SOURCE=$(InputPath)
236
237"$(OutDir)\$(TargetName).ex_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
238 compress $(OutDir)\$(TargetName).exe $(OutDir)\$(TargetName).ex_
239
240# End Custom Build
241
242!ELSEIF "$(CFG)" == "Install - Win32 Release"
243
244# PROP BASE Use_MFC 2
245# PROP BASE Use_Debug_Libraries 0
246# PROP BASE Output_Dir "Install\Release"
247# PROP BASE Intermediate_Dir "Install\Release"
248# PROP BASE Target_Dir "Install"
249# PROP Use_MFC 0
250# PROP Use_Debug_Libraries 0
251# PROP Output_Dir "Install\Release"
252# PROP Intermediate_Dir "Install\Release"
253# PROP Target_Dir "Install"
254OUTDIR=.\Install\Release
255INTDIR=.\Install\Release
256
257ALL : "KINSole - Win32 Release" "$(OUTDIR)\Install.exe"
258
259CLEAN :
260 -@erase "$(INTDIR)\install.obj"
261 -@erase "$(INTDIR)\Install.res"
262 -@erase "$(OUTDIR)\Install.exe"
263
264"$(OUTDIR)" :
265 if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
266
267CPP=cl.exe
268# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
269# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
270CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\
271 "_MBCS" /Fp"$(INTDIR)/Install.pch" /YX /Fo"$(INTDIR)/" /c
272CPP_OBJS=.\Install\Release/
273CPP_SBRS=.\.
274
275.c{$(CPP_OBJS)}.obj:
276 $(CPP) $(CPP_PROJ) $<
277
278.cpp{$(CPP_OBJS)}.obj:
279 $(CPP) $(CPP_PROJ) $<
280
281.cxx{$(CPP_OBJS)}.obj:
282 $(CPP) $(CPP_PROJ) $<
283
284.c{$(CPP_SBRS)}.sbr:
285 $(CPP) $(CPP_PROJ) $<
286
287.cpp{$(CPP_SBRS)}.sbr:
288 $(CPP) $(CPP_PROJ) $<
289
290.cxx{$(CPP_SBRS)}.sbr:
291 $(CPP) $(CPP_PROJ) $<
292
293MTL=mktyplib.exe
294# ADD BASE MTL /nologo /D "NDEBUG" /win32
295# ADD MTL /nologo /D "NDEBUG" /win32
296MTL_PROJ=/nologo /D "NDEBUG" /win32
297RSC=rc.exe
298# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
299# ADD RSC /l 0x409 /d "NDEBUG"
300RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Install.res" /d "NDEBUG"
301BSC32=bscmake.exe
302# ADD BASE BSC32 /nologo
303# ADD BSC32 /nologo
304BSC32_FLAGS=/nologo /o"$(OUTDIR)/Install.bsc"
305BSC32_SBRS= \
306
307LINK32=link.exe
308# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
309# 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
310LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
311 advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
312 odbccp32.lib version.lib /nologo /subsystem:windows /incremental:no\
313 /pdb:"$(OUTDIR)/Install.pdb" /machine:I386 /out:"$(OUTDIR)/Install.exe"
314LINK32_OBJS= \
315 "$(INTDIR)\install.obj" \
316 "$(INTDIR)\Install.res"
317
318"$(OUTDIR)\Install.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
319 $(LINK32) @<<
320 $(LINK32_FLAGS) $(LINK32_OBJS)
321<<
322
323!ELSEIF "$(CFG)" == "Install - Win32 Debug"
324
325# PROP BASE Use_MFC 2
326# PROP BASE Use_Debug_Libraries 1
327# PROP BASE Output_Dir "Install\Debug"
328# PROP BASE Intermediate_Dir "Install\Debug"
329# PROP BASE Target_Dir "Install"
330# PROP Use_MFC 0
331# PROP Use_Debug_Libraries 1
332# PROP Output_Dir "Install\Debug"
333# PROP Intermediate_Dir "Install\Debug"
334# PROP Target_Dir "Install"
335OUTDIR=.\Install\Debug
336INTDIR=.\Install\Debug
337
338ALL : "KINSole - Win32 Debug" "$(OUTDIR)\Install.exe"
339
340CLEAN :
341 -@erase "$(INTDIR)\install.obj"
342 -@erase "$(INTDIR)\Install.res"
343 -@erase "$(INTDIR)\vc40.idb"
344 -@erase "$(INTDIR)\vc40.pdb"
345 -@erase "$(OUTDIR)\Install.exe"
346 -@erase "$(OUTDIR)\Install.ilk"
347 -@erase "$(OUTDIR)\Install.pdb"
348
349"$(OUTDIR)" :
350 if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
351
352CPP=cl.exe
353# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /YX /c
354# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
355CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
356 /D "_MBCS" /Fp"$(INTDIR)/Install.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
357CPP_OBJS=.\Install\Debug/
358CPP_SBRS=.\.
359
360.c{$(CPP_OBJS)}.obj:
361 $(CPP) $(CPP_PROJ) $<
362
363.cpp{$(CPP_OBJS)}.obj:
364 $(CPP) $(CPP_PROJ) $<
365
366.cxx{$(CPP_OBJS)}.obj:
367 $(CPP) $(CPP_PROJ) $<
368
369.c{$(CPP_SBRS)}.sbr:
370 $(CPP) $(CPP_PROJ) $<
371
372.cpp{$(CPP_SBRS)}.sbr:
373 $(CPP) $(CPP_PROJ) $<
374
375.cxx{$(CPP_SBRS)}.sbr:
376 $(CPP) $(CPP_PROJ) $<
377
378MTL=mktyplib.exe
379# ADD BASE MTL /nologo /D "_DEBUG" /win32
380# ADD MTL /nologo /D "_DEBUG" /win32
381MTL_PROJ=/nologo /D "_DEBUG" /win32
382RSC=rc.exe
383# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
384# ADD RSC /l 0x409 /d "_DEBUG"
385RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Install.res" /d "_DEBUG"
386BSC32=bscmake.exe
387# ADD BASE BSC32 /nologo
388# ADD BSC32 /nologo
389BSC32_FLAGS=/nologo /o"$(OUTDIR)/Install.bsc"
390BSC32_SBRS= \
391
392LINK32=link.exe
393# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386
394# 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 /debug /machine:I386
395LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
396 advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
397 odbccp32.lib version.lib /nologo /subsystem:windows /incremental:yes\
398 /pdb:"$(OUTDIR)/Install.pdb" /debug /machine:I386 /out:"$(OUTDIR)/Install.exe"
399LINK32_OBJS= \
400 "$(INTDIR)\install.obj" \
401 "$(INTDIR)\Install.res"
402
403"$(OUTDIR)\Install.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
404 $(LINK32) @<<
405 $(LINK32_FLAGS) $(LINK32_OBJS)
406<<
407
408!ENDIF
409
410################################################################################
411# Begin Target
412
413# Name "KINSole - Win32 Release"
414# Name "KINSole - Win32 Debug"
415
416!IF "$(CFG)" == "KINSole - Win32 Release"
417
418!ELSEIF "$(CFG)" == "KINSole - Win32 Debug"
419
420!ENDIF
421
422################################################################################
423# Begin Source File
424
425SOURCE=.\KINSole.cpp
426DEP_CPP_KINSO=\
427 ".\NAWS.cpp"\
428 ".\NEW-ENVIRON.cpp"\
429 ".\options.cpp"\
430 ".\status.cpp"\
431 ".\terminal.cpp"\
432 ".\TIMING-MARK.cpp"\
433 ".\TTY.cpp"\
434 ".\VT100.cpp"\
435
436
437"$(INTDIR)\KINSole.obj" : $(SOURCE) $(DEP_CPP_KINSO) "$(INTDIR)"
438
439
440# End Source File
441################################################################################
442# Begin Source File
443
444SOURCE=.\kinsole.rc
445DEP_RSC_KINSOL=\
446 ".\res\kinsole.ico"\
447
448
449"$(INTDIR)\KINSole.res" : $(SOURCE) $(DEP_RSC_KINSOL) "$(INTDIR)"
450 $(RSC) $(RSC_PROJ) $(SOURCE)
451
452
453# End Source File
454################################################################################
455# Begin Source File
456
457SOURCE=.\VT100.cpp
458# PROP Exclude_From_Build 1
459# End Source File
460################################################################################
461# Begin Source File
462
463SOURCE=".\NEW-ENVIRON.cpp"
464# PROP Exclude_From_Build 1
465# End Source File
466################################################################################
467# Begin Source File
468
469SOURCE=.\help\kinsole.hpj
470
471!IF "$(CFG)" == "KINSole - Win32 Release"
472
473# Begin Custom Build - Building Help
474OutDir=.\Release
475TargetName=kinsole
476InputPath=.\help\kinsole.hpj
477
478BuildCmds= \
479 makehelp \
480 compress $(OutDir)\$(TargetName).hlp $(OutDir)\$(TargetName).hl_ \
481 compress $(OutDir)\$(TargetName).cnt $(OutDir)\$(TargetName).cn_ \
482
483
484"$(OutDir)\$(TargetName).hlp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
485 $(BuildCmds)
486
487"$(OutDir)\$(TargetName).cnt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
488 $(BuildCmds)
489
490"$(OutDir)\$(TargetName).hl_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
491 $(BuildCmds)
492
493"$(OutDir)\$(TargetName).cn_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
494 $(BuildCmds)
495# End Custom Build
496
497!ELSEIF "$(CFG)" == "KINSole - Win32 Debug"
498
499# Begin Custom Build - Building Help
500OutDir=.\Debug
501TargetName=kinsole
502InputPath=.\help\kinsole.hpj
503
504BuildCmds= \
505 makehelp \
506 compress $(OutDir)\$(TargetName).hlp $(OutDir)\$(TargetName).hl_ \
507 compress $(OutDir)\$(TargetName).cnt $(OutDir)\$(TargetName).cn_ \
508
509
510"$(OutDir)\$(TargetName).hlp" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
511 $(BuildCmds)
512
513"$(OutDir)\$(TargetName).cnt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
514 $(BuildCmds)
515
516"$(OutDir)\$(TargetName).hl_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
517 $(BuildCmds)
518
519"$(OutDir)\$(TargetName).cn_" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
520 $(BuildCmds)
521# End Custom Build
522
523!ENDIF
524
525# End Source File
526# End Target
527################################################################################
528# Begin Target
529
530# Name "Install - Win32 Release"
531# Name "Install - Win32 Debug"
532
533!IF "$(CFG)" == "Install - Win32 Release"
534
535!ELSEIF "$(CFG)" == "Install - Win32 Debug"
536
537!ENDIF
538
539################################################################################
540# Begin Source File
541
542SOURCE=.\Install\Install.rc
543DEP_RSC_INSTA=\
544 ".\Install\Custom.rch"\
545 ".\shared-data\install-icon.ico"\
546
547
548!IF "$(CFG)" == "Install - Win32 Release"
549
550
551"$(INTDIR)\Install.res" : $(SOURCE) $(DEP_RSC_INSTA) "$(INTDIR)"
552 $(RSC) /l 0x409 /fo"$(INTDIR)/Install.res" /i "Install" /d "NDEBUG"\
553 $(SOURCE)
554
555
556!ELSEIF "$(CFG)" == "Install - Win32 Debug"
557
558
559"$(INTDIR)\Install.res" : $(SOURCE) $(DEP_RSC_INSTA) "$(INTDIR)"
560 $(RSC) /l 0x409 /fo"$(INTDIR)/Install.res" /i "Install" /d "_DEBUG"\
561 $(SOURCE)
562
563
564!ENDIF
565
566# End Source File
567################################################################################
568# Begin Source File
569
570SOURCE=.\Install\install.cpp
571DEP_CPP_INSTAL=\
572 ".\shared-code\install.h"\
573
574
575"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTAL) "$(INTDIR)"
576 $(CPP) $(CPP_PROJ) $(SOURCE)
577
578
579# End Source File
580################################################################################
581# Begin Project Dependency
582
583# Project_Dep_Name "KINSole"
584
585!IF "$(CFG)" == "Install - Win32 Release"
586
587"KINSole - Win32 Release" :
588 $(MAKE) /$(MAKEFLAGS) /F ".\kinsole.mak" CFG="KINSole - Win32 Release"
589
590!ELSEIF "$(CFG)" == "Install - Win32 Debug"
591
592"KINSole - Win32 Debug" :
593 $(MAKE) /$(MAKEFLAGS) /F ".\kinsole.mak" CFG="KINSole - Win32 Debug"
594
595!ENDIF
596
597# End Project Dependency
598################################################################################
599# Begin Source File
600
601SOURCE=.\help\kinsole.hpj
602
603!IF "$(CFG)" == "Install - Win32 Release"
604
605!ELSEIF "$(CFG)" == "Install - Win32 Debug"
606
607!ENDIF
608
609# End Source File
610# End Target
611# End Project
612################################################################################
diff --git a/kinsole.rc b/kinsole.rc
new file mode 100644
index 0000000..b789f37
--- a/dev/null
+++ b/kinsole.rc
@@ -0,0 +1,115 @@
1//Microsoft Developer Studio generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/////////////////////////////////////////////////////////////////////////////
16// English (U.S.) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19#ifdef _WIN32
20LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21#pragma code_page(1252)
22#endif //_WIN32
23
24/////////////////////////////////////////////////////////////////////////////
25//
26// Icon
27//
28
29// Icon with lowest ID value placed first to ensure application icon
30// remains consistent on all systems.
31IDI_IKON ICON DISCARDABLE "res/kinsole.ico"
32
33#ifdef APSTUDIO_INVOKED
34/////////////////////////////////////////////////////////////////////////////
35//
36// TEXTINCLUDE
37//
38
391 TEXTINCLUDE DISCARDABLE
40BEGIN
41 "resource.h\0"
42END
43
442 TEXTINCLUDE DISCARDABLE
45BEGIN
46 "#include ""afxres.h""\r\n"
47 "\0"
48END
49
503 TEXTINCLUDE DISCARDABLE
51BEGIN
52 "\r\n"
53 "\0"
54END
55
56#endif // APSTUDIO_INVOKED
57
58
59#ifndef _MAC
60/////////////////////////////////////////////////////////////////////////////
61//
62// Version
63//
64
65VS_VERSION_INFO VERSIONINFO
66 FILEVERSION 1,0,0,3
67 PRODUCTVERSION 1,0,0,3
68 FILEFLAGSMASK 0x3fL
69#ifdef _DEBUG
70 FILEFLAGS 0x29L
71#else
72 FILEFLAGS 0x28L
73#endif
74 FILEOS 0x4L
75 FILETYPE 0x1L
76 FILESUBTYPE 0x3L
77BEGIN
78 BLOCK "StringFileInfo"
79 BEGIN
80 BLOCK "040904b0"
81 BEGIN
82 VALUE "CompanyName", "Klever Group (http://www.klever.net)\0"
83 VALUE "FileDescription", "KINSole, telnet client\0"
84 VALUE "FileVersion", "1, 0, 0, 3\0"
85 VALUE "InternalName", "KINSOLE\0"
86 VALUE "LegalCopyright", "Copyright © 1998, 2002 Klever Group (http://www.klever.net/)\0"
87 VALUE "LegalTrademarks", "Klever Group (http://www.klevernet/)\0"
88 VALUE "OriginalFilename", "KINSOLE.EXE\0"
89 VALUE "ProductName", "KINSole\0"
90 VALUE "ProductVersion", "1, 0, 0, 3\0"
91 END
92 END
93 BLOCK "VarFileInfo"
94 BEGIN
95 VALUE "Translation", 0x409, 1200
96 END
97END
98
99#endif // !_MAC
100
101#endif // English (U.S.) resources
102/////////////////////////////////////////////////////////////////////////////
103
104
105
106#ifndef APSTUDIO_INVOKED
107/////////////////////////////////////////////////////////////////////////////
108//
109// Generated from the TEXTINCLUDE 3 resource.
110//
111
112
113/////////////////////////////////////////////////////////////////////////////
114#endif // not APSTUDIO_INVOKED
115
diff --git a/makehelp.bat b/makehelp.bat
new file mode 100644
index 0000000..531b2dc
--- a/dev/null
+++ b/makehelp.bat
@@ -0,0 +1,11 @@
1@echo off
2echo Building RTF file
3xsltproc -o help/kinsole.rtf shared-code/kinhelp.xsl help/kinsole.xml
4echo Building Win32 Help files
5start /wait hcrtf -x "help\kinsole.hpj"
6echo.
7if exist Debug\nul copy "help\kinsole.hlp" Debug
8if exist Debug\nul copy "help\kinsole.cnt" Debug
9if exist Release\nul copy "help\kinsole.hlp" Release
10if exist Release\nul copy "help\kinsole.cnt" Release
11echo.
diff --git a/options.cpp b/options.cpp
new file mode 100644
index 0000000..171ae4a
--- a/dev/null
+++ b/options.cpp
@@ -0,0 +1,371 @@
1
2 enum_TOption {
3 toBinaryTransmission = 0,
4 toEcho = 1, // Done.
5 toReconnection = 2,
6 toSuppressGA = 3, // Eaten
7 toApproxMsgSizeNegotiation = 4,
8 toStatus = 5, // Half-implemented
9 toTimingMark = 6,
10 toRemoteControlledTransAndEcho = 7,
11 toOutputLineWidth = 8,
12 toOutputPageSize = 9,
13 toOutputCRDisposition = 10,
14 toOutputHTabstops = 11,
15 toOutputHTabDisposition = 12,
16 toOutputFFDisposition = 13,
17 toOutputVTabstops = 14,
18 toOutputVTabDisposition = 15,
19 toOutputLFDisposition = 16,
20 toExtendedASCII = 17,
21 toLogout = 18,
22 toByteMacro = 19,
23 toDET = 20,
24 toSUPDUP = 22,// ???
25 toSUPDUPOutput = 22,
26 toSendLocation = 23,
27 toTerminalType =24, // Done.
28 toEndOfRecord = 25,
29 toTACACSUserId = 26,
30 toOutputMarking = 27,
31 toTerminalLocationNumber = 28,
32 toTelnet3270Regime = 29,
33 toX3PAD = 30,
34 toNAWS = 31, // Done.
35 toTerminalSpeed = 32, // No need to implement, really.
36 toRemoteFlowControl = 33, // !!!
37 toLineMode = 34,
38 toXDisplayLocation = 35, // No need to implement until we
39 // do our own X-Server.
40 toEnvironmentOption = 36,
41 toAuthenticationOption = 37,
42 toEncryptionOption = 38,
43 toNewEnviron = 39, // Need to implement
44 toTN3270E = 40,
45 toExtendedOptionsList = 255
46};
47
48 struct TOption{
49 enum _state {
50 stateNone=0, stateNo, stateYes, stateWantNo, stateWantYes
51 };
52 UINT m_StateU:3;// State - US
53 UINT m_StateH:3;// State - HIM
54 int m_Q:1;
55 int m_Supported:1;
56 UINT m_SBCluster;
57 UINT m_AllocatedSB;
58 UINT m_StoredSB;
59 LPBYTE m_SB;
60
61 BOOL (*m_OnDo)();
62 BOOL (*m_OnDont)();
63 BOOL (*m_OnWill)();
64 BOOL (*m_OnWont)();
65 BOOL (*m_OnSB)(LPBYTE data,UINT size);
66 BOOL (*m_OnInit)();
67
68 BOOL OnDo() { return m_OnDo?(*m_OnDo)():FALSE; }
69 BOOL OnDont() { return m_OnDont?(*m_OnDont)():FALSE; }
70 BOOL OnWill() { return m_OnWill?(*m_OnWill)():FALSE; }
71 BOOL OnWont() { return m_OnWont?(*m_OnWont)():FALSE; }
72 BOOL OnSB(LPBYTE data,UINT size) { return m_OnSB?(*m_OnSB)(data,size):FALSE; }
73 BOOL OnInit() { return m_OnInit?(*m_OnInit)():FALSE; }
74
75 BOOL StoreSByte(BYTE c) {
76 if(m_AllocatedSB>=m_StoredSB){
77 ASSERT(m_SBCluster);
78 LPBYTE nsb = new BYTE[m_AllocatedSB+m_SBCluster];
79 ASSERT(nsb);
80 if(m_StoredSB){
81 ASSERT(m_SB);
82 memmove(nsb,m_SB,m_StoredSB);
83 }
84 if(m_SB)
85 delete m_SB;
86 m_SB = nsb;
87 }
88 ASSERT(m_SB);
89 m_SB[m_StoredSB++]=c;
90 return TRUE;
91 }
92 BOOL CleanSB() {
93 if(m_SB)
94 delete m_SB;
95 m_SB = NULL;
96 m_AllocatedSB=m_StoredSB=0;
97 return TRUE;
98 }
99
100 }Options[256];
101
102
103BOOL AskWill(BYTE o);
104BOOL AskWont(BYTE o);
105BOOL AskDo(BYTE o);
106BOOL AskDont(BYTE o);
107
108#include "NAWS.cpp"
109#include "terminal.cpp"
110#include "status.cpp"
111#include "NEW-ENVIRON.cpp"
112#include "TIMING-MARK.cpp"
113
114 BOOL On_ACK(){ return TRUE; }
115
116
117void InitOptionsTable()
118{
119 memset(Options,0,sizeof(Options));
120 // Echo
121 Options[toEcho].m_OnDo = On_ACK;
122 Options[toEcho].m_OnDont = On_ACK;
123 Options[toEcho].m_OnWill = On_ACK;
124 Options[toEcho].m_OnWont = On_ACK;
125 // Suppress Go-Ahead
126 Options[toSuppressGA].m_OnWill = On_ACK;
127 Options[toSuppressGA].m_OnDo = On_ACK;
128 // Status
129 Options[toStatus].m_OnWill = statusOnWill;
130 Options[toStatus].m_OnDo = statusOnDo;
131 Options[toStatus].m_OnSB = statusOnSB;
132 // Terminal Type;
133 Options[toTerminalType].m_OnDo = terminaltypeOnDo;
134 Options[toTerminalType].m_OnSB = terminaltypeOnSB;
135 Options[toTerminalType].m_OnInit = terminaltypeOnInit;
136 Options[toTerminalType].m_SBCluster = 32;
137 // NAWS
138 Options[toNAWS].m_OnDo = nawsOnDo;
139 Options[toNAWS].m_SBCluster = 16;
140 // New Environment
141 Options[toNewEnviron].m_OnDo = newenvironOnDo;
142 Options[toNewEnviron].m_OnDont = newenvironOnDont;
143 Options[toNewEnviron].m_OnSB = newenvironOnSB;
144 Options[toNewEnviron].m_SBCluster = 32;
145 // Timing Mark
146 Options[toTimingMark].m_OnDo = tmOnDo;
147 Options[toTimingMark].m_OnWill = tmOnWill;
148
149 for(int tmp=0;tmp<(sizeof(Options)/sizeof(*Options));tmp++){
150 TOption& to = Options[tmp];
151 to.OnInit();
152 if(to.m_OnDo || to.m_OnDont || to.m_OnWill || to.m_OnWont
153 || to.m_OnSB || to.m_OnInit)
154 to.m_Supported=TRUE;
155 if(!to.m_SBCluster)
156 to.m_SBCluster=128;
157 }
158}
159
160void ProcessDO(BYTE c)
161{
162TOption& to = Options[c];
163 // Ignore this junk if we're already in desired mode of operation
164 if(to.m_StateU==TOption::stateYes){
165 connState = cstateNone;
166 return;
167 }
168 TRACE1("He want us to DO %d\n",(WORD)c);
169 if(!to.m_Supported){
170 TRACE1("Unsupported option = %d\n",(WORD)c);
171 // Option is not suported - send WONT and switch to stateNo unless
172 // we've already denied this option.
173 if(to.m_StateU == TOption::stateNone){
174 VERIFY(ShowUnwill(c));
175 to.m_StateU = TOption::stateNo;
176 }
177 }else{
178 // Okay, if we do - we do and tell him so, unless we asked for it.
179 // Otherwise - Tell him we're not about to.
180 if(to.OnDo()){
181 if(to.m_StateU!=TOption::stateWantYes)
182 VERIFY(ShowWill(c));
183 to.m_StateU = TOption::stateYes;
184 }else{
185 if(to.m_StateU!=TOption::stateWantNo)
186 VERIFY(ShowUnwill(c));
187 to.m_StateU = TOption::stateNo;
188 }
189 }
190 connState = cstateNone;
191}
192
193void ProcessWILL(BYTE c)
194{
195TOption& to = Options[c];
196 // Ignore this junk if we consider him already in this mode
197 if(to.m_StateH==TOption::stateYes){
198 connState = cstateNone;
199 return;
200 }
201 TRACE1("He WILL %d\n",(WORD)c);
202 if(!to.m_Supported){
203 TRACE1("Unsupported option = %d\n",(WORD)c);
204 // Since we don't expect remote end to use this option - beg him
205 // not to go for it unless we think we already did.
206 if(to.m_StateH == TOption::stateNone){
207 VERIFY(BegDont(c));
208 to.m_StateH = TOption::stateNo;
209 }
210 }else{
211 if(to.OnWill()){
212 // We've accepted this - tell him to go ahead if we thought he's
213 // in opposite state and adjust our vision/
214 if(to.m_StateH!=TOption::stateWantYes)
215 VERIFY(BegDo(c));
216 to.m_StateH = TOption::stateYes;
217 }else{
218 if(to.m_StateH!=TOption::stateWantNo)
219 VERIFY(BegDont(c));
220 to.m_StateH = TOption::stateNo;
221 }
222 }
223 connState = cstateNone;
224}
225
226void ProcessWONT(BYTE c)
227{
228TOption& to = Options[c];
229 // Ignore this junk if we consider him already in this mode
230 if(to.m_StateH==TOption::stateNo){
231 connState = cstateNone;
232 return;
233 }
234 TRACE1("He WONT %d\n",(WORD)c);
235 if(!to.m_Supported){
236 TRACE1("Unsupported option = %d\n",(WORD)c);
237 // Since we don't expect remote end to use this option - beg him
238 // not to go for it unless we think we already did.
239 if(to.m_StateH == TOption::stateNone){
240 VERIFY(BegDont(c));
241 to.m_StateH = TOption::stateNo;
242 }
243 }else{
244 if(to.OnWont()){
245 // We've accepted this - tell him to go ahead if we thought he's
246 // in opposite state and adjust our vision/
247 if(to.m_StateH!=TOption::stateWantNo)
248 VERIFY(BegDont(c));
249 to.m_StateH = TOption::stateNo;
250 }else{
251 if(to.m_StateH!=TOption::stateWantYes)
252 VERIFY(BegDo(c));
253 to.m_StateH = TOption::stateYes;
254 }
255 }
256 connState = cstateNone;
257}
258
259void ProcessDONT(BYTE c)
260{
261TOption& to = Options[c];
262 // Ignore this junk if we consider him already in this mode
263 if(to.m_StateU==TOption::stateNo){
264 connState = cstateNone;
265 return;
266 }
267 TRACE1("He want us to DONT %d\n",(WORD)c);
268 if(!to.m_Supported){
269 TRACE1("DONT for unsupported option = %d\n",(WORD)c);
270 // Since we don't expect remote end to use this option - beg him
271 // not to go for it unless we think we already did.
272 if(to.m_StateU == TOption::stateNone){
273 VERIFY(ShowUnwill(c));
274 to.m_StateU = TOption::stateNo;
275 }
276 }else{
277 if(to.OnDont()){
278 if(to.m_StateU!=TOption::stateWantNo)
279 VERIFY(ShowUnwill(c));
280 to.m_StateU = TOption::stateNo;
281 }else{
282 if(to.m_StateU!=TOption::stateWantYes)
283 VERIFY(ShowWill(c));
284 to.m_StateU = TOption::stateYes;
285 }
286 }
287 connState = cstateNone;
288}
289
290void ProcessSBData(BYTE c)
291{
292 switch(connState){
293 case cstateSBData:
294 if(c==tnIAC){
295 connState=cstateSBDataIAC;
296 return;
297 }
298 break;
299 case cstateSBDataIAC:
300 if(c==tnSE){
301 // Just let option handler process the data
302 TOption& to = Options[negOption];
303 to.OnSB(to.m_SB,to.m_StoredSB);
304 to.CleanSB();
305 connState = cstateNone;
306 return;
307 }
308 break;
309 default:
310 ASSERT(FALSE);
311 break;
312 }
313TOption& to = Options[negOption];
314 to.StoreSByte(c);
315}
316
317BOOL AskWill(BYTE o)
318{
319TOption& to = Options[o];
320 if(to.m_StateU==TOption::stateYes || to.m_StateU==TOption::stateWantYes)
321 return TRUE;
322#ifdef _DEBUG
323 if(to.m_StateU==TOption::stateWantNo)
324 TRACE1("NEED TO QUEUE %d\n",(WORD)o);
325#endif
326 VERIFY(ShowWill(o));
327 to.m_StateU=TOption::stateWantYes;
328 return TRUE;
329}
330
331BOOL AskUnwill(BYTE o)
332{
333TOption& to = Options[o];
334 if(to.m_StateU==TOption::stateNo || to.m_StateU==TOption::stateWantNo)
335 return TRUE;
336#ifdef _DEBUG
337 if(to.m_StateU==TOption::stateWantNo)
338 TRACE1("NEED TO QUEUE %d\n",(WORD)o);
339#endif
340 VERIFY(ShowUnwill(o));
341 to.m_StateU=TOption::stateWantNo;
342 return TRUE;
343}
344
345BOOL AskDo(BYTE o)
346{
347TOption& to = Options[o];
348 if(to.m_StateH==TOption::stateYes || to.m_StateH==TOption::stateWantYes)
349 return TRUE;
350#ifdef _DEBUG
351 if(to.m_StateH==TOption::stateWantNo)
352 TRACE1("NEED TO QUEUE %d\n",(WORD)o);
353#endif
354 VERIFY(BegDo(o));
355 to.m_StateH=TOption::stateWantYes;
356 return TRUE;
357}
358
359BOOL AskDont(BYTE o)
360{
361TOption& to = Options[o];
362 if(to.m_StateH==TOption::stateNo || to.m_StateH==TOption::stateWantNo)
363 return TRUE;
364#ifdef _DEBUG
365 if(to.m_StateH==TOption::stateWantYes)
366 TRACE1("NEED TO QUEUE %d\n",(WORD)o);
367#endif
368 VERIFY(BegDont(o));
369 to.m_StateH=TOption::stateWantNo;
370 return TRUE;
371}
diff --git a/res/kinsole.ico b/res/kinsole.ico
new file mode 100644
index 0000000..e355485
--- a/dev/null
+++ b/res/kinsole.ico
Binary files differ
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..64dd500
--- a/dev/null
+++ b/resource.h
@@ -0,0 +1,16 @@
1//{{NO_DEPENDENCIES}}
2// Microsoft Developer Studio generated include file.
3// Used by KINSole.rc
4//
5#define IDI_IKON 101
6
7// Next default values for new objects
8//
9#ifdef APSTUDIO_INVOKED
10#ifndef APSTUDIO_READONLY_SYMBOLS
11#define _APS_NEXT_RESOURCE_VALUE 103
12#define _APS_NEXT_COMMAND_VALUE 40001
13#define _APS_NEXT_CONTROL_VALUE 1000
14#define _APS_NEXT_SYMED_VALUE 101
15#endif
16#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 @@
1 #ifndef__BTREENDEX_H
2 #define__BTREENDEX_H
3
4#include "Dynamide.h"
5
6namespace Klever {
7
8template<class key,class value,int treeOrder,int cluster>
9 class CBTreendex : public CObject{
10public:
11 typedef LONG CBTPageRef;
12 struct CBTRecordRef {
13 CBTPageRef m_Page;
14 INT m_Offset;
15 CBTRecordRef(CBTPageRef page=-1,INT offset=-1) : m_Page(page), m_Offset(offset) {}
16 };
17 class CBTRecord : public CObject {
18 public:
19 CBTPageRef m_ptrLeft;
20 CBTPageRef m_ptrRight;
21 key m_Key;
22 value m_Value;
23 CBTRecord() : m_ptrLeft(-1), m_ptrRight(-1) {}
24 CBTRecord(key& _key,value& _value,CBTPageRef left=-1,CBTPageRef right=-1) : m_Key(_key), m_Value(_value), m_ptrLeft(left), m_ptrRight(right) {}
25 CBTRecord(CBTRecord& r) : m_Key(r.m_Key), m_Value(r.m_Value), m_ptrLeft(r.m_ptrLeft), m_ptrRight(r.m_ptrRight) {}
26
27 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;}
28
29 void Serialize(CArchive& ar) {
30 if(ar.IsStoring()){
31 ar << m_ptrLeft;
32 ar << m_ptrRight;
33 }else{
34 ar >> m_ptrLeft;
35 ar >> m_ptrRight;
36 }
37 SerializeElements(ar,&m_Key,1);
38 SerializeElements(ar,&m_Value,1);
39 }
40 };
41 class CBTPage : public CArray<CBTRecord,CBTRecord&> {
42 public:
43 void Serialize(CArchive& ar) {
44 int nCount = -1;
45 if(ar.IsStoring()){
46 nCount = GetSize();
47 ar << nCount;
48 }else{
49 nCount = 0;
50 ar >> nCount;
51 RemoveAll();
52 SetSize(nCount);
53 }
54 for(int tmp=0;tmp<nCount;tmp++)
55 ElementAt(tmp).Serialize(ar);
56 }
57 };
58 typedef CDynamide<256,cluster> CBTDyna;
59 typedef CBTDyna::CDynaFile CBTDynaFile;
60 typedef CArray<CBTRecordRef,CBTRecordRef&> CBTRStack;
61
62 CBTDyna m_BT;
63 struct_btCrap {
64 BOOL m_bRootSet;
65 CBTPageRef m_Root;
66 } *m_BTCrap;
67 BOOL m_bRO;
68 CBTRStack m_btStack;
69 CBTPage m_stackTop;
70
71 CBTreendex() {}
72 ~CBTreendex() { Close(); }
73 BOOL Attach(CFile* file,BOOL bAutodelete) {
74 m_bRO = FALSE;
75 if(!m_BT.Attach(file,bAutodelete))
76 return FALSE;
77 return Attach();
78 }
79 BOOL Open(LPCTSTR file,BOOL bReadOnly) {
80 if(!m_BT.Open(file,bReadOnly))
81 return FALSE;
82 m_bRO = bReadOnly;
83 return Attach();
84 }
85 BOOL Create(LPCTSTR file) {
86 try{
87 CFile* f = new CFile(file,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyRead|CFile::shareDenyWrite|CFile::typeBinary);
88 ASSERT(f);
89 return Attach(f,TRUE);
90 }catch(CException* e){
91 e->Delete();
92 return FALSE;
93 }
94 }
95 BOOL Attach() {
96 ASSERT(m_BT.IsOpened());
97 m_BTCrap = (_btCrap*)m_BT.m_FB.crap;
98 if(!m_BTCrap->m_bRootSet){
99 m_BTCrap->m_Root = AllocatePage();
100 if(m_BTCrap->m_Root<0)
101 return FALSE;
102 m_BTCrap->m_bRootSet = TRUE;
103 m_BT.Write1stBlock();
104 }
105 return TRUE;
106 }
107 BOOL Close() {
108 m_BT.Close();
109 return TRUE;
110 }
111 BOOL IsOpened() {
112 return m_BT.IsOpened();
113 }
114
115 BOOL Lookup(key& _key,value& value) {
116 if(!IsOpened())
117 return FALSE;
118 ASSERT(m_BTCrap->m_bRootSet);
119 if(!SeekToPage(_key))
120 return FALSE;
121 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
122 if(rr.m_Offset<0)
123 return FALSE;
124 ASSERT(rr.m_Offset<m_stackTop.GetSize());
125 if(_key != m_stackTop[rr.m_Offset].m_Key)
126 return FALSE;
127 value = m_stackTop[rr.m_Offset].m_Value;
128 return TRUE;
129 }
130 BOOL Add(key& _key,value& _value) {
131 if(!IsOpened())
132 return FALSE;
133 ASSERT(m_BTCrap->m_bRootSet);
134 if(!SeekToPage(_key))
135 return FALSE;
136 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
137 CBTRecord nuRecord(_key,_value);
138 if(rr.m_Offset<0){
139 if(m_stackTop.GetSize())
140 nuRecord.m_ptrLeft = m_stackTop[m_stackTop.GetUpperBound()].m_ptrRight;
141 }else if(rr.m_Offset==0){
142 nuRecord.m_ptrRight = m_stackTop[0].m_ptrLeft;
143 }else{
144 nuRecord.m_ptrLeft = m_stackTop[rr.m_Offset-1].m_ptrRight;
145 nuRecord.m_ptrRight = m_stackTop[rr.m_Offset].m_ptrLeft;
146 }
147 // ASSERT(rr.m_Offset==0 || (m_stackTop[rr.m_Offset-1].m_Key<_key && m_stackTop[rr.m_Offset-1].m_ptrRight<0));
148 // ASSERT(rr.m_Offset<0 || m_stackTop[rr.m_Offset].m_Key>=_key && m_stackTop[rr.m_Offset].m_ptrLeft<0);
149 if(rr.m_Offset>=0 && m_stackTop[rr.m_Offset].m_Key==_key){
150 // Exact match found - just replace.
151 m_stackTop[rr.m_Offset].m_Value = _value;
152 if(!SavePage(rr.m_Page,m_stackTop))
153 return FALSE;
154 return TRUE;
155 }
156 // Split the page and propagate the split if needed..
157 // Insert new element at rr.m_Offset..
158 BOOL nuisnew = TRUE;
159 for(int sp=m_btStack.GetUpperBound();sp>=0;sp--){
160 CBTPageRef opr = m_btStack[sp].m_Page;
161 int iAt = m_btStack[sp].m_Offset;
162 CBTPage op;
163 VERIFY(LoadPage(opr,op));
164 if(iAt<0)
165 iAt = op.GetSize();
166 else{
167 if(op[iAt].m_Key<nuRecord.m_Key)
168 iAt++;
169 ASSERT(iAt==op.GetSize() || op[iAt].m_Key > nuRecord.m_Key);
170 }
171 op.InsertAt(iAt,nuRecord);
172 if(iAt>0)
173 op[iAt-1].m_ptrRight=nuRecord.m_ptrLeft;
174 if(iAt<op.GetUpperBound())
175 op[iAt+1].m_ptrLeft=nuRecord.m_ptrRight;
176 if(op.GetSize()<=treeOrder*2){
177 // This isn't causing overflow
178 VERIFY(SavePage(opr,op));
179 return TRUE;
180 }
181 TRACE0("Split\n");
182 ASSERT(op.GetSize()==(treeOrder*2+1));
183 CBTPageRef npr = AllocatePage();
184 ASSERT(npr>=0);
185 CBTPage np;
186 ASSERT(LoadPage(npr,np));
187 ASSERT(!np.GetSize());
188 nuRecord = op[treeOrder];
189 if(iAt==treeOrder){
190 // We're inserting central element! - drop out the stack top if this is still new one
191 for(int tmp=0;tmp<treeOrder;tmp++)
192 np.InsertAt(tmp,op[tmp]);
193 op.RemoveAt(0,treeOrder+1);
194 nuRecord.m_ptrLeft = npr;
195 nuRecord.m_ptrRight = opr;
196 if(nuisnew)
197 m_btStack.RemoveAt(m_btStack.GetUpperBound());
198 }else{
199 if(iAt<treeOrder){
200 // We're inserting in the left subtree.
201 // Make newpage the right one and forget it.
202 for(int tmp=0;tmp<treeOrder;tmp++)
203 np.InsertAt(tmp,op[tmp+treeOrder+1]);
204 op.RemoveAt(treeOrder,treeOrder+1);
205 nuRecord.m_ptrLeft = opr;
206 nuRecord.m_ptrRight = npr;
207 }else{
208 // We're inserting in the right subtree.
209 // Make newpage the left one, forget it, but also adjust offset in the stack
210 for(int tmp=0;tmp<treeOrder;tmp++)
211 np.InsertAt(tmp,op[tmp]);
212 op.RemoveAt(0,treeOrder+1);
213 nuRecord.m_ptrLeft = npr;
214 nuRecord.m_ptrRight = opr;
215 m_btStack[sp].m_Offset-=treeOrder+1;
216 }
217 // Note that we're not inserting new element anymore.
218 nuisnew = FALSE;
219 }
220 // Do, excessive sanity checks and save pages
221 ASSERT(op.GetSize());
222 ASSERT(np.GetSize());
223 VERIFY(SavePage(opr,op));
224 VERIFY(SavePage(npr,np));
225 }
226 // Here we have root page overflow, which means that we're simply putting new
227 // record in this brand new root page and also inserting this page on the bottom of the stack
228 CBTPageRef nuroot = AllocatePage();
229 ASSERT(nuroot>=0);
230 CBTPage nurpa;
231 ASSERT(LoadPage(nuroot,nurpa));
232 ASSERT(!nurpa.GetSize());
233 nurpa.Add(nuRecord);
234 VERIFY(SavePage(nuroot,nurpa));
235 m_btStack.InsertAt(0,CBTRecordRef(nuroot,0));
236 m_BTCrap->m_Root = nuroot;
237 m_BT.Write1stBlock();
238 return TRUE;
239 }
240 BOOL Delete(key& _key) {
241 if(!IsOpened())
242 return FALSE;
243 ASSERT(m_BTCrap->m_bRootSet);
244 value _value;
245 if(!Lookup(_key,_value))
246 return FALSE;
247 // Found key, check if it's a leaf
248 {
249 CBTRecordRef* rr = &m_btStack[m_btStack.GetUpperBound()];
250 int rrIdx = m_btStack.GetUpperBound();
251 if(m_stackTop[rr->m_Offset].m_ptrLeft>=0){
252 ASSERT(m_stackTop[rr->m_Offset].m_ptrRight>=0);
253 // It isn't - scan for the _next_ key and do dirty deeds
254 m_btStack.Add(CBTRecordRef(m_stackTop[rr->m_Offset].m_ptrRight,0));
255 for(;;){
256 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
257 if(!LoadPage(rr.m_Page,m_stackTop))
258 return FALSE;
259 if(m_stackTop[0].m_ptrLeft<0)
260 break;
261 m_btStack.Add(CBTRecordRef(m_stackTop[0].m_ptrLeft,0));
262 }
263 // We have a leaf node here, replace victim with the first element and kill it.
264 CBTPage uppage;
265 rr = &m_btStack[rrIdx];
266 if(!LoadPage(rr->m_Page,uppage))
267 return FALSE;
268 uppage[rr->m_Offset].m_Key=m_stackTop[0].m_Key; uppage[rr->m_Offset].m_Value=m_stackTop[0].m_Value;
269 m_stackTop.RemoveAt(0);
270 if(!(SavePage(rr->m_Page,uppage) && SavePage(m_btStack[m_btStack.GetUpperBound()].m_Page,m_stackTop)))
271 return FALSE;
272 }else{
273 ASSERT(m_stackTop[rr->m_Offset].m_ptrRight<0);
274 m_stackTop.RemoveAt(rr->m_Offset);
275 if(!SavePage(rr->m_Page,m_stackTop))
276 return FALSE;
277 }
278 }
279 // We have a page to check for underflow at the top of the stack now.
280 for(;;){
281 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
282 if(!LoadPage(rr.m_Page,m_stackTop))
283 return FALSE;
284 if(m_stackTop.GetSize()>=treeOrder || m_btStack.GetSize()==1)
285 return TRUE;
286 CBTRecordRef& rr1 = m_btStack[m_btStack.GetUpperBound()-1];
287 CBTPage daddy;
288 if(!LoadPage(rr1.m_Page,daddy))
289 return FALSE;
290 CBTPageRef nPage = daddy[rr1.m_Offset].m_ptrRight;
291 BOOL bRight=TRUE;
292 if(nPage<0 || nPage==rr.m_Page){
293 nPage = daddy[rr1.m_Offset].m_ptrLeft;
294 bRight = FALSE;
295 }
296 ASSERT(nPage>=0 && nPage!=rr.m_Page);
297 CBTPage neighbor;
298 if(!LoadPage(nPage,neighbor))
299 return FALSE;
300 // Here we have possibly two cases:
301 // 1. Neighboring page can share some data with use, then do share and leave
302 // 2. Neighboring page is of treeorder in size, then merge and propagate
303 if(neighbor.GetSize()>treeOrder){
304 TRACE0("Redistributing..\n");
305 // Borrow some data from there.
306 int toBorrow = neighbor.GetSize()-treeOrder;
307 toBorrow=toBorrow/2+1;
308 ASSERT(toBorrow);
309 if(bRight)
310 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));
311 else
312 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));
313 for(toBorrow--;toBorrow;toBorrow--){
314 if(bRight){
315 m_stackTop.Add(neighbor[0]);
316 neighbor.RemoveAt(0);
317 }else{
318 m_stackTop.InsertAt(0,neighbor[neighbor.GetUpperBound()]);
319 neighbor.RemoveAt(neighbor.GetUpperBound());
320 }
321 }
322 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;
323 neighbor.RemoveAt(bRight?0:neighbor.GetUpperBound());
324 if(!(SavePage(rr1.m_Page,daddy) && SavePage(nPage,neighbor) && SavePage(rr.m_Page,m_stackTop)))
325 return FALSE;
326 rr.m_Offset = -1;// *** Point to the next??
327 return TRUE;
328 }
329 TRACE0("Merging..\n");
330 // We need to merge pages here..
331 // We will merge them at stacktop, then we'll discard neighbor guy..
332 if(bRight)
333 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));
334 else
335 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));
336 if(bRight){
337 while(neighbor.GetSize()){
338 m_stackTop.Add(neighbor[0]);
339 neighbor.RemoveAt(0);
340 }
341 }else{
342 while(neighbor.GetSize()){
343 m_stackTop.InsertAt(0,neighbor[neighbor.GetUpperBound()]);
344 neighbor.RemoveAt(neighbor.GetUpperBound());
345 }
346 }
347 if(rr1.m_Offset>0)
348 daddy[rr1.m_Offset-1].m_ptrRight=rr.m_Page;
349 if(rr1.m_Offset<daddy.GetUpperBound())
350 daddy[rr1.m_Offset+1].m_ptrLeft=rr.m_Page;
351 daddy.RemoveAt(rr1.m_Offset);
352 if(!(SavePage(rr1.m_Page,daddy) && SavePage(rr.m_Page,m_stackTop)))
353 return FALSE;
354 VERIFY(DeallocatePage(nPage));
355 m_btStack.RemoveAt(m_btStack.GetUpperBound());
356 }
357 return FALSE;
358 }
359 BOOL GoFirst() {
360 if(!IsOpened())
361 return FALSE;
362 ASSERT(m_BTCrap->m_bRootSet);
363 m_btStack.RemoveAll();
364 m_btStack.Add(CBTRecordRef(m_BTCrap->m_Root,-1));
365 for(;;){
366 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
367 if(!LoadPage(rr.m_Page,m_stackTop))
368 return FALSE;
369 if(!m_stackTop.GetSize()){
370 ASSERT(m_btStack.GetSize()==1);
371 return FALSE;
372 }
373 rr.m_Offset = 0;
374 if(m_stackTop[rr.m_Offset].m_ptrLeft<0)
375 return TRUE;
376 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,-1));
377 }
378 }
379 BOOL GoLast() {
380 if(!IsOpened())
381 return FALSE;
382 ASSERT(m_BTCrap->m_bRootSet);
383 m_btStack.RemoveAll();
384 m_btStack.Add(CBTRecordRef(m_BTCrap->m_Root,-1));
385 for(;;){
386 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
387 if(!LoadPage(rr.m_Page,m_stackTop))
388 return FALSE;
389 if(!m_stackTop.GetSize()){
390 ASSERT(m_btStack.GetSize()==1);
391 return FALSE;
392 }
393 rr.m_Offset = m_stackTop.GetUpperBound();
394 if(m_stackTop[rr.m_Offset].m_ptrRight<0)
395 return TRUE;
396 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset++].m_ptrRight,-1));
397 }
398 }
399 BOOL GoNext() {
400 if(!IsOpened())
401 return FALSE;
402 if(!(m_btStack.GetSize() && m_btStack[m_btStack.GetUpperBound()].m_Offset>=0))
403 return FALSE;
404 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
405 if(!LoadPage(rr.m_Page,m_stackTop))
406 return FALSE;
407 ASSERT(rr.m_Offset<m_stackTop.GetSize());
408 if(m_stackTop[rr.m_Offset].m_ptrRight>=0){
409 // Advance pointer in this page and dive into subtree
410 // going left and left until we have nowhere to go.
411 // TRACE1("Dive into page %lu",m_stackTop[rr.m_Offset].m_ptrRight);
412 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset++].m_ptrRight,0));
413 for(;;){
414 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
415 ASSERT(rr.m_Offset==0);
416 if(!LoadPage(rr.m_Page,m_stackTop))
417 return FALSE;
418 if(m_stackTop[rr.m_Offset].m_ptrLeft<0)
419 break;
420 // TRACE1(", %lu",m_stackTop[rr.m_Offset].m_ptrLeft);
421 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,0));
422 }
423 // TRACE0("\n");
424 return TRUE;
425 }else if(rr.m_Offset<m_stackTop.GetUpperBound()){
426 rr.m_Offset++;
427 return TRUE;
428 }
429 // We're at the end of page go up until we're done or we have data.
430 m_btStack.RemoveAt(m_btStack.GetUpperBound());
431 // TRACE0("Go up");
432 while(m_btStack.GetSize()){
433 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
434 if(!LoadPage(rr.m_Page,m_stackTop))
435 return FALSE;
436 if(rr.m_Offset<m_stackTop.GetSize()){
437 // TRACE0("\n");
438 return TRUE;
439 }
440 // TRACE0(", up");
441 m_btStack.RemoveAt(m_btStack.GetUpperBound());
442 }
443 // TRACE0("\nBtree is done\n");
444 return FALSE;
445 }
446 BOOL GoPrev() {
447 if(!IsOpened())
448 return FALSE;
449 if(!(m_btStack.GetSize() && m_btStack[m_btStack.GetUpperBound()].m_Offset>=0))
450 return FALSE;
451 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
452 if(!LoadPage(rr.m_Page,m_stackTop))
453 return FALSE;
454 ASSERT(rr.m_Offset<m_stackTop.GetSize());
455 if(m_stackTop[rr.m_Offset].m_ptrLeft>=0){
456 // Dive in and go right and right from the rightmost until
457 // we have nowhere to go.
458 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,-1));
459 for(;;){
460 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
461 if(!LoadPage(rr.m_Page,m_stackTop))
462 return FALSE;
463 rr.m_Offset = m_stackTop.GetUpperBound();
464 if(m_stackTop[rr.m_Offset].m_ptrRight<0)
465 return TRUE;
466 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset++].m_ptrRight,-1));
467 }
468 return TRUE;
469 }else if(rr.m_Offset>0){
470 rr.m_Offset--;
471 return TRUE;
472 }
473 // We're at the leftmost element in page - go up and left until we're
474 // done or we have data.
475 m_btStack.RemoveAt(m_btStack.GetUpperBound());
476 while(m_btStack.GetSize()){
477 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
478 if(!LoadPage(rr.m_Page,m_stackTop))
479 return FALSE;
480 rr.m_Offset--;
481 if(rr.m_Offset>=0)
482 return TRUE;
483 m_btStack.RemoveAt(m_btStack.GetUpperBound());
484 }
485 // No more data - we were at the first element in tree.
486 return FALSE;
487 }
488 BOOL GetThis(key& _key,value& _value) {
489 if(!IsOpened())
490 return FALSE;
491 // *** MORE CHECKING
492 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
493 if(!LoadPage(rr.m_Page,m_stackTop))
494 return FALSE;
495 _key = m_stackTop[rr.m_Offset].m_Key;
496 _value = m_stackTop[rr.m_Offset].m_Value;
497 return TRUE;
498 }
499
500 BOOL SeekToPage(const key& _key) {
501 ASSERT(IsOpened());
502 ASSERT(m_BTCrap->m_bRootSet);
503 m_btStack.RemoveAll();
504 m_btStack.Add(CBTRecordRef(m_BTCrap->m_Root,-1));
505 for(;;){
506 CBTRecordRef& rr = m_btStack[m_btStack.GetUpperBound()];
507 if(!LoadPage(rr.m_Page,m_stackTop))
508 return FALSE;
509 ASSERT(m_stackTop.GetSize() || !m_btStack.GetUpperBound());
510 if(!m_stackTop.GetSize()){
511 rr.m_Offset=-1;
512 return TRUE;
513 }
514 for(rr.m_Offset=0;rr.m_Offset<m_stackTop.GetSize();rr.m_Offset++){
515 if(_key == m_stackTop[rr.m_Offset].m_Key)
516 return TRUE;
517 if(_key < m_stackTop[rr.m_Offset].m_Key){
518 ASSERT(rr.m_Offset==0 || m_stackTop[rr.m_Offset].m_ptrLeft==m_stackTop[rr.m_Offset-1].m_ptrRight);
519 if(m_stackTop[rr.m_Offset].m_ptrLeft<0)
520 return TRUE;
521 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrLeft,-1));
522 break;
523 }
524 if(rr.m_Offset==m_stackTop.GetUpperBound()){
525 if(m_stackTop[rr.m_Offset].m_ptrRight<0){
526 rr.m_Offset=-1;
527 return TRUE;
528 }
529 m_btStack.Add(CBTRecordRef(m_stackTop[rr.m_Offset].m_ptrRight,-1));
530 break;
531 }
532 }
533 }
534 }
535
536 BOOL LoadPage(CBTPageRef ref,CBTPage& page) {
537 CFile* pageFile = m_BT.OpenFile(ref);
538 if(!pageFile)
539 return FALSE;
540 BOOL rv = TRUE;
541 try{
542 CArchive ar(pageFile,CArchive::load);
543 page.Serialize(ar);
544 if(m_bRO)
545 page.FreeExtra();// ** ???
546 ar.Close();
547 }catch(CException* e){
548 e->Delete();
549 rv = FALSE;
550 }
551 delete pageFile;
552 return rv;
553 }
554 BOOL SavePage(CBTPageRef ref,CBTPage& page) {
555 CFile* pageFile = m_BT.OpenFile(ref);
556 if(!pageFile)
557 return FALSE;
558 BOOL rv = TRUE;
559 try{
560 CArchive ar(pageFile,CArchive::store);
561 page.Serialize(ar);
562 ar.Close();
563 }catch(CException* e){
564 e->Delete();
565 rv = FALSE;
566 }
567 delete pageFile;
568 return rv;
569 }
570 CBTPageRef AllocatePage() {
571 CBTDynaFile* pageFile = m_BT.CreateFile();
572 if(!pageFile)
573 return -1;
574 CBTPage nothing;
575 CBTPageRef rv = pageFile->GetFile();
576 try{
577 CArchive ar(pageFile,CArchive::store);
578 nothing.Serialize(ar);
579 ar.Close();
580 }catch(CException* e){
581 e->Delete();
582 rv = -1;
583 }
584 delete pageFile;
585 return rv;
586 }
587 BOOL DeallocatePage(CBTPageRef ref) {
588 return m_BT.DeleteFile(ref);
589 }
590
591};
592
593};
594
595 #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 @@
1 #ifndef__BELLSNWHISTLES_H
2#define __BELLSNWHISTLES_H
3
4 class CBellsNWhistles{
5public:
6 class CBang {
7 public:
8 CString m_codeName;
9 enum_bangType {
10 bangNone, bangSpeaker, bangSystem, bangResource,
11 bangWaveform
12 }m_type;
13 BOOL m_bLoop;
14 union{
15 UINT system;
16 LPCTSTR resource;
17 LPCTSTR wave;
18
19 LPCTSTR str;
20 UINT id;
21 };
22 CString m_strWave;
23 CBang() : m_type(bangNone), m_bLoop(FALSE) {}
24 };
25 typedef CTypedPtrMap<CMapStringToPtr,CString,CBang*> CBangs;
26 structCBelling {
27 LPCSTR snd;
28 HMODULE hm;
29 DWORD flags;
30 CBelling(LPCSTR snd,HMODULE hm,DWORD flags) : snd(snd), hm(hm),
31 flags(flags) {}
32 CBelling(CBelling& s) : snd(s.snd), hm(s.hm), flags(s.flags) {}
33 CBelling& operator=(CBelling& s) {
34 snd=s.snd; hm=s.hm; flags=s.flags;
35 return *this;
36 }
37 };
38 typedef CBelling* Whistling;
39
40 CBangs m_bangs;
41
42 ~CBellsNWhistles() {
43 POSITION p = m_bangs.GetStartPosition();
44 while(p){
45 CString s; CBang* b;
46 m_bangs.GetNextAssoc(p,s,b);
47 delete b;
48 }
49 m_bangs.RemoveAll();
50 }
51
52 BOOL AssignSound(LPCTSTR codeName,LPCTSTR id,CBang::_bangType type=CBang::bangWaveform) {
53 CString cn = codeName;
54 cn.MakeLower();
55 CBang* b;
56 if(!m_bangs.Lookup(cn,b)) {
57 b = new CBang;
58 b->m_codeName=cn;
59 m_bangs[cn]=b;
60 }
61 b->m_type=type;
62 b->str = id;
63 if(type==CBang::bangWaveform){
64 b->m_strWave=id; b->str = b->m_strWave;
65 }
66 return TRUE;
67 }
68 BOOL AssignSound(LPCTSTR codeName,UINT nID,CBang::_bangType type=CBang::bangResource) {
69 CString cn = codeName;
70 cn.MakeLower();
71 CBang* b;
72 if(!m_bangs.Lookup(cn,b)) {
73 b = new CBang;
74 b->m_codeName=cn;
75 m_bangs[cn]=b;
76 }
77 b->m_type=type;
78 b->id = nID;
79 ASSERT(type!=CBang::bangWaveform);
80 return TRUE;
81 }
82 BOOL UnassignSound(LPCTSTR codeName) {
83 CString cn = codeName;
84 cn.MakeLower();
85 CBang* b;
86 if(m_bangs.Lookup(cn,b)) {
87 m_bangs.RemoveKey(cn);
88 delete b;
89 return TRUE;
90 }
91 return FALSE;
92 }
93
94 Whistling StartSound(LPCTSTR codeName) {
95 Whistling* rv = NULL;
96 CString cn = codeName;
97 CBang* b;
98 if(!m_bangs.Lookup(cn,b)){
99 ::PlaySound(cn,AfxGetInstanceHandle(),SND_ASYNC|SND_NODEFAULT|SND_NOWAIT|SND_FILENAME);
100 return NULL;
101 }
102 UINT flags = SND_ASYNC|SND_NODEFAULT|SND_NOWAIT;
103 LPCSTR snd = NULL;
104 switch(b->m_type){
105 case CBang::bangNone: return NULL;
106 case CBang::bangSpeaker: MessageBeep(0xFFFFFFFF); return NULL;
107 case CBang::bangSystem: MessageBeep(b->system); return NULL;
108 case CBang::bangResource:
109 snd = b->resource;
110 flags|=SND_RESOURCE; break;
111 case CBang::bangWaveform:
112 snd = b->wave;
113 flags|=SND_FILENAME; break;
114#ifdef _DEBUG
115 default:
116 ASSERT(FALSE); return NULL;
117#endif
118 }
119 if(b->m_bLoop)
120 flags|=SND_LOOP;
121 HMODULE hm = AfxGetInstanceHandle();
122 if(!::PlaySound(snd,hm,flags))
123 return NULL;
124 return b->m_bLoop?new CBelling(snd,hm,flags):NULL;
125 }
126 BOOL StopSound(Whistling whistle) {
127 if(!whistle)
128 return FALSE;
129 ::PlaySound(whistle->snd,whistle->hm,whistle->flags|SND_PURGE);
130 delete whistle;
131 return TRUE;
132 }
133 UINT FillInCombo(CComboBox* combo) {
134 POSITION p = m_bangs.GetStartPosition();
135 UINT rv = 0;
136 while(p) {
137 CString s;
138 CBang* b;
139 m_bangs.GetNextAssoc(p,s,b);
140 combo->AddString(s);
141 }
142 return rv;
143 }
144};
145
146 #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 @@
1 #ifndef__BITSET_H
2#define __BITSET_H
3
4namespace Klever {
5
6 class CBitSet: public CObject {
7public:
8 CWordArray m_Bits;
9 ULONG m_BitsInSet;
10 enum{
11 bitsPerWord = sizeof(WORD)*8
12 };
13
14 CBitSet(ULONG size = 0) : m_BitsInSet(0) { SetSize(size); }
15 CBitSet(CBitSet& o) : m_BitsInSet(0) { CopyFrom(o); }
16
17 void SetSize(ULONG size,BOOL bFillOnes=FALSE) {
18 UINT os = m_Bits.GetSize();
19 UINT ns = (size+bitsPerWord-1)/bitsPerWord;
20 if(os==ns){
21 if(os){
22 if(bFillOnes)
23 m_Bits[m_BitsInSet/bitsPerWord]|=(~(WORD)0)<<(m_BitsInSet%bitsPerWord);
24 else
25 m_Bits[m_BitsInSet/bitsPerWord]&=~((~(WORD)0)<<(m_BitsInSet%bitsPerWord));
26 }
27 m_BitsInSet=size;
28 }else{
29 // *?* ASSERT((!os) || (((os-1)*bitsPerWord)<=m_BitsInSet && m_BitsInSet<(os*bitsPerWord)));
30 if(os<ns){
31 m_Bits.SetSize(ns);
32 if(bFillOnes)
33 m_Bits[m_BitsInSet/bitsPerWord]|=(~(WORD)0)<<(m_BitsInSet%bitsPerWord);
34 else
35 m_Bits[m_BitsInSet/bitsPerWord]&=~((~(WORD)0)<<(m_BitsInSet%bitsPerWord));
36 WORD* ws = m_Bits.GetData();
37 ASSERT(ws);
38 memset(&ws[os],bFillOnes?0xFF:0,(ns-os)*sizeof(WORD));
39 m_BitsInSet=size;
40 }else{
41 m_Bits.SetSize(ns);
42 m_BitsInSet=size;
43 }
44 }
45 }
46 BOOL BitSet(UINT bit,BOOL bGrow=TRUE) { return SetBit(bit,TRUE,bGrow); }
47 BOOL BitClear(UINT bit,BOOL bGrow=TRUE) { return SetBit(bit,FALSE,bGrow); }
48 BOOL SetBit(UINT bit,BOOL state,BOOL bGrow=TRUE) {
49 if(m_BitsInSet<=bit){
50 if(!bGrow)
51 return FALSE;
52 SetSize(bit+1);
53 }
54 WORD mask = ((WORD)1)<<(bit%bitsPerWord);
55 if(state)
56 m_Bits[bit/bitsPerWord]|=mask;
57 else
58 m_Bits[bit/bitsPerWord]&=~mask;
59 return TRUE;
60 }
61 BOOL IsSet(UINT bit) {
62 if(m_BitsInSet<=bit)
63 return FALSE;
64 return (m_Bits[bit/bitsPerWord]&(((WORD)1)<<(bit%bitsPerWord)))!=0;
65 }
66 void Invert() {
67 for(int i=m_Bits.GetUpperBound();i>=0;i--)
68 m_Bits[i]=~m_Bits[i];
69 }
70 CBitSet& operator&=(CBitSet& o) {
71 if(o.m_BitsInSet<m_BitsInSet)
72 SetSize(o.m_BitsInSet);
73 for(int i=m_Bits.GetUpperBound();i>=0;i--)
74 m_Bits[i]&=o.m_Bits[i];
75 return *this;
76 }
77 CBitSet& operator|=(CBitSet& o) {
78 if(o.m_BitsInSet>m_BitsInSet)
79 SetSize(o.m_BitsInSet);
80 for(int i=o.m_Bits.GetUpperBound();i>=0;i--)
81 m_Bits[i]|=o.m_Bits[i];
82 return *this;
83 }
84 CBitSet& operator=(CBitSet& o) {
85 CopyFrom(o);
86 return *this;
87 }
88 void CopyFrom(CBitSet& o) {
89 m_BitsInSet=o.m_BitsInSet;
90 m_Bits.Copy(o.m_Bits);
91 }
92 void Serialize(CArchive& ar) {
93 if(ar.IsStoring()){
94 ar << m_BitsInSet;
95 m_Bits.Serialize(ar);
96 }else{
97 ar >> m_BitsInSet;
98 m_Bits.Serialize(ar);
99 }
100 }
101};
102
103};
104
105#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 @@
1#ifndef __DYNAMIDE_H
2#define __DYNAMIDE_H
3
4#include "LRUCache.h"
5
6namespace Klever {
7
8template<int fbSize,int bSize>
9class CDynamide : public CObject {
10 structfirstBlock {
11 LONGfreeFile;
12 BYTEcrap[fbSize-sizeof(LONG)];
13 };
14 structtheBlock {
15 LONGnext;
16 BYTEdata[bSize-sizeof(LONG)];
17 };
18public:
19 static firstBlock FirstBlock;
20 static theBlock TheBlock;
21private:
22 classCDynaCache : public CLRUCache<DWORD,DWORD,theBlock> {
23 public:
24 CFile* m_File;
25 BOOL m_bAutodelete;
26 CDynaCache(CFile* file,BOOL bAutodelete=TRUE) : CLRUCache<DWORD,DWORD,theBlock>(64) {
27 m_File=file;
28 m_bAutodelete=bAutodelete;
29 }
30 virtual ~CDynaCache() {
31 Flush();
32 if(m_bAutodelete){
33 m_File->Close();
34 delete m_File;
35 }
36 }
37 virtual BOOL _ReadIn(DWORD idx,theBlock* data) {
38 LONG p = sizeof(firstBlock)+idx*sizeof(theBlock);
39 LONG s = m_File->Seek(p,CFile::begin);
40 if(p==s){
41 UINT rb = m_File->Read(data,sizeof(*data));
42 if(rb==sizeof(*data))
43 return TRUE;
44 if(rb)
45 return FALSE;
46 memset(data,0,sizeof(*data));
47 data->next=-1;
48 try{
49 m_File->Write(data,sizeof(*data));
50 }catch(CException* e){
51 e->Delete();
52 return FALSE;
53 }
54 }else{
55 LONG togo = p-s;
56 ASSERT(togo>0);
57 ASSERT(!(togo%sizeof(theBlock)));
58 memset(data,0,sizeof(*data));
59 data->next=-1;
60 while(togo>=0){
61 try{
62 m_File->Write(data,sizeof(*data));
63 }catch(CException* e){
64 e->Delete();
65 return FALSE;
66 }
67 }
68 }
69 return TRUE;
70 }
71 virtual BOOL _WriteOut(DWORD idx,theBlock* data) {
72 LONG p = sizeof(firstBlock)+idx*sizeof(theBlock);
73 LONG s = m_File->Seek(p,CFile::begin);
74 if(p!=s)
75 return FALSE;
76 try{
77 m_File->Write(data,sizeof(*data));
78 }catch(CException* e){
79 e->Delete();
80 return FALSE;
81 }
82 return TRUE;
83 }
84 DWORD AllocateNode() {
85 LONG l = m_File->GetLength();
86 ASSERT(!((l-sizeof(firstBlock))%sizeof(theBlock)));
87 m_File->SetLength(l+sizeof(theBlock));
88 return (l-sizeof(firstBlock))/sizeof(theBlock);
89 }
90 BOOL Read1stBlock(firstBlock* fb) {
91 m_File->SeekToBegin();
92 UINT rb = m_File->Read(fb,sizeof(*fb));
93 if(rb==sizeof(*fb))
94 return TRUE;
95 if(rb)
96 return FALSE;
97 memset(fb,0,sizeof(*fb));
98 fb->freeFile = -1;
99 try{
100 m_File->Write(fb,sizeof(*fb));
101 }catch(CException* e){
102 e->Delete();
103 return FALSE;
104 }
105 return TRUE;
106 }
107 BOOL Write1stBlock(firstBlock* fb) {
108 m_File->SeekToBegin();
109 try{
110 m_File->Write(fb,sizeof(*fb));
111 }catch(CException* e){
112 e->Delete();
113 return FALSE;
114 }
115 return TRUE;
116 }
117 };
118public:
119 class CDynaFile : public CFile{
120 public:
121 CDynamide<fbSize,bSize>* m_Daddy;
122 CArray<LONG,LONG> m_Blocks;
123 LONG m_Position;
124
125 CDynaFile(CDynamide<fbSize,bSize>* daddy) : m_Daddy(NULL) { AttachToDaddy(daddy); }
126 virtual ~CDynaFile() { Close(); DetachFromDaddy(); }
127
128 void AttachToDaddy(CDynamide<fbSize,bSize>* daddy) {
129 ASSERT(!m_Daddy);
130 ASSERT(daddy);
131 m_Daddy=daddy;
132 m_Daddy->AttachDynaFile(this);
133 }
134 void DetachFromDaddy() {
135 ASSERT(m_Daddy);
136 ASSERT(!IsOpened());
137 m_Daddy->DetachDynaFile(this);
138 m_Daddy=NULL;
139 }
140
141 BOOL Create() {
142 if(IsOpened())
143 return FALSE;
144 m_Blocks.SetAtGrow(0,m_Daddy->Allocate());
145 ASSERT(m_Blocks[0]>=0);
146 m_Position=0;
147 return TRUE;
148 }
149 BOOL Open(LONG fb) {
150 if(IsOpened())
151 return FALSE;
152 ASSERT(fb>=0);
153 theBlock* b;
154 do{
155 m_Blocks.Add(fb);
156 b = m_Daddy->m_File->GetCached(fb);
157 ASSERT(b);
158 fb=b->next;
159 if(m_Blocks[m_Blocks.GetUpperBound()]==fb)
160 return FALSE;
161 }while(fb>=0);
162 m_Position=0;
163 return TRUE;
164 }
165
166 LONG GetFile() {
167 if(!IsOpened())
168 return -1;
169 return m_Blocks[0];
170 }
171 virtual DWORD GetPosition() const {
172 if(!IsOpened())
173 return 0;
174 if(m_Position<0)
175 return 0;
176 if(m_Position>GetLength())
177 return GetLength();
178 return m_Position;
179 }
180 virtual CString GetFileName() {
181 CString rv;
182 if(IsOpened())
183 rv.Format("0x%08lX",m_Blocks[0]);
184 else
185 rv.Format("None");
186 return rv;
187 }
188 virtual CString GetFileTitle() { return GetFileName(); }
189 virtual CString GetFilePath() { return GetFileName(); }
190 virtual void SetFilePath(LPCTSTR lpszNewName) { ASSERT(FALSE); }
191
192 virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL) { ASSERT(FALSE); return FALSE; }
193 virtual CFile* Duplicate() { ASSERT(FALSE); return NULL; }
194
195 virtual LONG Seek(LONG lOff, UINT nFrom) {
196 if(!IsOpened())
197 return -1;
198 switch(nFrom){
199 case CFile::begin:
200 m_Position=lOff;
201 break;
202 case CFile::current:
203 m_Position+=lOff;
204 break;
205 case CFile::end:
206 m_Position=GetLength()+lOff;
207 break;
208 default:
209 ASSERT(FALSE);
210 return -1;
211 }
212 if(m_Position<0)
213 m_Position=0;
214 if(m_Position>GetLength())
215 m_Position=GetLength();
216 return m_Position;
217 }
218 virtual void SetLength(DWORD dwNewLen) {
219 if(!IsOpened())
220 return;
221 if(dwNewLen<GetLength()){
222 dwNewLen=dwNewLen+sizeof(TheBlock.data);
223 dwNewLen-=dwNewLen%sizeof(TheBlock.data);
224 while(dwNewLen<GetLength() && m_Blocks.GetSize()>1){
225 LONG mb = m_Blocks[m_Blocks.GetUpperBound()];
226 LONG mb1 = m_Blocks[m_Blocks.GetUpperBound()-1];
227 theBlock* b = m_Daddy->m_File->GetCached(mb1);
228 ASSERT(b);
229 ASSERT(b->next==mb);
230 b->next=-1;
231 m_Daddy->m_File->MakeDirty(mb1);
232 m_Daddy->Deallocate(mb);
233 m_Blocks.SetSize(m_Blocks.GetSize()-1);
234 }
235 }else{
236 while(dwNewLen>GetLength()){
237 LONG mb = m_Blocks[m_Blocks.GetUpperBound()];
238 LONG newBlock = m_Daddy->Allocate();
239 ASSERT(newBlock>=0);
240 theBlock* b = m_Daddy->m_File->GetCached(mb);
241 ASSERT(b);
242 ASSERT(b->next<0);
243 b->next=newBlock;
244 m_Daddy->m_File->MakeDirty(mb);
245 m_Blocks.Add(newBlock);
246 }
247 }
248 }
249 virtual DWORD GetLength() const {
250 return ((long)m_Blocks.GetSize())*((long)sizeof(TheBlock.data));
251 }
252
253 virtual UINT Read(void* lpBuf, UINT nCount) {
254 UINT rv = 0;
255 ASSERT(m_Position>=0 && m_Position<=GetLength());
256 LPBYTE data = (LPBYTE)lpBuf;
257 while(nCount && m_Position<GetLength()){
258 UINT bn = m_Position/sizeof(TheBlock.data);
259 UINT bo = m_Position%sizeof(TheBlock.data);
260 theBlock* b = m_Daddy->m_File->GetCached(m_Blocks[bn]);
261 ASSERT(b);
262 UINT bc = min(nCount,sizeof(TheBlock.data)-bo);
263 memmove(data,&b->data[bo],bc);
264 nCount-=bc;
265 data=&data[bc];
266 rv+=bc;
267 m_Position+=bc;
268 }
269 return rv;
270 }
271 virtual void Write(const void* lpBuf, UINT nCount) {
272 ASSERT(m_Position>=0 && m_Position<=GetLength());
273 LPBYTE data = (LPBYTE)lpBuf;
274 while(nCount){
275 UINT bn = m_Position/sizeof(TheBlock.data);
276 UINT bo = m_Position%sizeof(TheBlock.data);
277 while(bn>=m_Blocks.GetSize()){
278 LONG mb = m_Blocks[m_Blocks.GetUpperBound()];
279 LONG newBlock = m_Daddy->Allocate();
280 ASSERT(newBlock>=0);
281 theBlock* b = m_Daddy->m_File->GetCached(mb);
282 ASSERT(b);
283 ASSERT(b->next<0);
284 b->next=newBlock;
285 m_Daddy->m_File->MakeDirty(mb);
286 m_Blocks.Add(newBlock);
287 }
288 theBlock* b = m_Daddy->m_File->GetCached(m_Blocks[bn]);
289 ASSERT(b);
290 UINT bc = min(nCount,sizeof(TheBlock.data)-bo);
291 memmove(&b->data[bo],data,bc);
292 m_Daddy->m_File->MakeDirty(m_Blocks[bn]);
293 nCount-=bc;
294 data=&data[bc];
295 m_Position+=bc;
296 }
297 }
298
299 virtual void LockRange(DWORD dwPos, DWORD dwCount) { ASSERT(FALSE); }
300 virtual void UnlockRange(DWORD dwPos, DWORD dwCount) { ASSERT(FALSE); }
301
302 virtual void Abort() { ASSERT(FALSE); }
303 virtual void Flush() {
304 m_Daddy->m_File->Flush();
305 }
306 virtual void Close() {
307 m_Blocks.RemoveAll();
308 }
309
310 BOOL IsOpened() const { return m_Blocks.GetSize()!=0; }
311 };
312
313 CDynaCache* m_File;
314 firstBlock m_FB;
315
316 CDynamide() : m_File(NULL) {}
317 ~CDynamide() { Close(); }
318
319 BOOL AttachDynaFile(CDynaFile* f) {
320 //ASSERT(!m_Files.Find(f));
321 //m_Files.AddHead(f);
322 return TRUE;
323 }
324 BOOL DetachDynaFile(CDynaFile* f) {
325 //POSITION p = m_Files.Find(f);
326 //ASSERT(p);
327 //m_Files.RemoveAt(p);
328 return TRUE;
329 }
330
331 BOOL Open(LPCTSTR file,BOOL bRO=FALSE) {
332 Close();
333 try{
334 CFile* f = new CFile(file,CFile::typeBinary|(bRO?CFile::modeRead|CFile::shareDenyWrite:CFile::modeReadWrite|CFile::shareDenyRead));
335 return Attach(f,TRUE);
336 }catch(CException* e){
337 e->Delete();
338 return FALSE;
339 }
340 }
341 BOOL Create(LPCTSTR file) {
342 Close();
343 try{
344 CFile* f = new CFile(file,CFile::typeBinary|CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyRead);
345 return Attach(f,TRUE);
346 }catch(CException* e){
347 e->Delete();
348 return FALSE;
349 }
350 }
351 BOOL Attach(CFile* file,BOOL bAutodelete=TRUE) {
352 if(IsOpened())
353 return FALSE;
354 m_File = new CDynaCache(file,bAutodelete);
355 if(!m_File->Read1stBlock(&m_FB)){
356 memset(&m_FB,0,sizeof(m_FB));
357 m_FB.freeFile=-1;
358 VERIFY(m_File->Write1stBlock(&m_FB));
359 }
360 return IsOpened();
361 }
362 // CFile* Detach();
363 BOOL Close() {
364 if(!IsOpened())
365 return FALSE;
366 m_File->Write1stBlock(&m_FB);
367 delete m_File;
368 m_File=NULL;
369 return TRUE;
370 }
371 BOOL IsOpened() {
372 return m_File != NULL;
373 }
374 BOOL Write1stBlock(void) {
375 if(!IsOpened())
376 return FALSE;
377 VERIFY(m_File->Write1stBlock(&m_FB));
378 return TRUE;
379 }
380
381 CDynaFile* CreateFile() {
382 CDynaFile* rv = new CDynaFile(this);
383 if(rv->Create())
384 return rv;
385 delete rv;
386 return NULL;
387 }
388 CDynaFile* OpenFile(LONG fb) {
389 CDynaFile* rv = new CDynaFile(this);
390 if(rv->Open(fb))
391 return rv;
392 delete rv;
393 return NULL;
394 }
395 BOOL DeleteFile(LONG fb) {
396 while(fb>=0){
397 theBlock* b = m_File->GetCached(fb);
398 LONG nb = b->next;
399 Deallocate(fb);
400 fb=nb;
401 }
402 return TRUE;
403 }
404
405 LONG Allocate() {
406 if(!IsOpened())
407 return -1;
408 if(m_FB.freeFile<0){
409 LONG rv = m_File->AllocateNode();
410 theBlock *b = m_File->GetCached(rv);
411 b->next=-1;
412 m_File->MakeDirty(rv);
413 return rv;
414 }
415 LONG rv = m_FB.freeFile;
416 theBlock *b = m_File->GetCached(rv);
417 m_FB.freeFile=b->next;
418 b->next=-1;
419 m_File->MakeDirty(rv);
420 m_File->Write1stBlock(&m_FB);
421 return rv;
422 }
423 BOOL Deallocate(LONG bk) {
424 if(!IsOpened())
425 return FALSE;
426 theBlock* b = m_File->GetCached(bk);
427 ASSERT(b);
428 if(m_FB.freeFile<0){
429 b->next=-1;
430 m_FB.freeFile=bk;
431 }else{
432 b->next=m_FB.freeFile;
433 m_FB.freeFile=bk;
434 }
435 m_File->MakeDirty(bk);
436 m_File->Write1stBlock(&m_FB);
437 return TRUE;
438 }
439};
440
441};
442
443#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 @@
1 #ifndef__FINDIFACE_H
2 #define__FINDIFACE_H
3
4#include "SNMPeer.h"
5#include "SNMPExtDLL.h"
6#include "SNMPOIDs.h"
7
8namespace Klever {
9
10inline BOOL FindIFace(in_addr& target,in_addr& source)
11{
12 DEFINE_OID(ipRouteDest, OIDipRouteDest);
13 DEFINE_OID(ipRouteMask, OIDipRouteMask);
14 DEFINE_OID(ipRouteIfIndex,OIDipRouteIfIndex);
15 DEFINE_OID(ipRouteMetric1,OIDipRouteMetric1);
16 DEFINE_OID(ipAdEntIfIndex,OIDipAdEntIfIndex);
17 DEFINE_OID(ipAdEntAddr, OIDipAdEntAddr);
18 struct _route{
19 int iface;
20 int metric;
21 DWORD nm;
22 }routes[16];
23int nRoutes = 0;
24CSNMPVarBindList vbl;
25 vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteDest,sizeof(ipRouteDest))));
26 vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteMask,sizeof(ipRouteMask))));
27 vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteIfIndex,sizeof(ipRouteIfIndex))));
28 vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipRouteMetric1,sizeof(ipRouteMetric1))));
29CSNMPExtDLL snmp("INETMIB1");
30 while(nRoutes<(sizeof(routes)/sizeof(routes[0]))){
31 if(
32 snmp.Request(CASNAny::typeASNGetNextRequest,vbl,vbl)
33 && vbl.GetCount() == 4
34 ){
35 POSITION p = vbl.GetHeadPosition();
36 _route r = {-1,-1};
37 in_addr d, m;
38 BOOL bD = FALSE, bM = FALSE;
39 while(p){
40 CSNMPVarBind& vb = vbl.GetNext(p);
41 if(
42 vb.IsName(ipRouteDest,sizeof(ipRouteDest))
43 && vb.value.type==CASNAny::typeASNIP
44 ){
45 d.s_addr=vb.value.value.ip.s_addr; bD = TRUE;
46 }else if(
47 vb.IsName(ipRouteMask,sizeof(ipRouteMask))
48 && vb.value.type==CASNAny::typeASNIP
49 ){
50 m.s_addr=vb.value.value.ip.s_addr; bM = TRUE;
51 }else if(
52 vb.IsName(ipRouteIfIndex,sizeof(ipRouteIfIndex))
53 && vb.value.type==CASNAny::typeASNInteger
54 ){
55 r.iface=vb.value.value.number;
56 }else if(
57 vb.IsName(ipRouteMetric1,sizeof(ipRouteMetric1))
58 && vb.value.type==CASNAny::typeASNInteger
59 ){
60 r.metric=vb.value.value.number;
61 }else
62 break;
63 }
64 if(r.iface<0 || r.metric<0 || (!bD) || (!bM))
65 break;
66 if((target.s_addr&m.s_addr)==(d.s_addr&m.s_addr)){
67 r.nm=htonl(m.s_addr);
68 memmove(&routes[nRoutes++],&r,sizeof(routes[0]));
69 }
70 }else
71 break;
72 }
73 if(!nRoutes)
74 return FALSE;
75int rn = 0;
76 if(nRoutes>1){
77 for(int tmp=1;tmp<nRoutes;tmp++)
78 if(
79 routes[tmp].metric<routes[rn].metric
80 || routes[tmp].nm>routes[rn].nm
81 )
82 rn = tmp;
83 }
84int iface = routes[rn].iface;
85 vbl.RemoveAll();
86 vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipAdEntAddr,sizeof(ipAdEntAddr))));
87 vbl.AddTail(CSNMPVarBind(CASNAny(CASNAny::typeASNOID,ipAdEntIfIndex,sizeof(ipAdEntIfIndex))));
88 for(;;){
89 if(
90 snmp.Request(CASNAny::typeASNGetNextRequest,vbl,vbl)
91 && vbl.GetCount()==2
92 ){
93 in_addr a; a.s_addr = INADDR_NONE;
94 int ifn = -1;
95 POSITION p = vbl.GetHeadPosition();
96 while(p){
97 CSNMPVarBind& vb = vbl.GetNext(p);
98 if(
99 vb.IsName(ipAdEntAddr,sizeof(ipAdEntAddr))
100 && vb.value.type==CASNAny::typeASNIP
101 ){
102 a.s_addr=vb.value.value.ip.s_addr;
103 }else if(
104 vb.IsName(ipAdEntIfIndex,sizeof(ipAdEntIfIndex))
105 && vb.value.type==CASNAny::typeASNInteger
106 ){
107 ifn = vb.value.value.number;
108 }else
109 break;
110 }
111 if(ifn<0)
112 break;
113 if(ifn==iface){
114 source.s_addr=a.s_addr;
115 return TRUE;
116 }
117 }else
118 break;
119 }
120 return FALSE;
121}
122
123};
124
125 #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 @@
1 #ifndef__LRUCACHE_H
2 #define__LRUCACHE_H
3
4namespace Klever {
5
6template<class IDX,class ARGIDX,class DATA>
7class CLRUCache : public CObject {
8public:
9 struct CacheEntry{
10 enum cacheState{
11 cacheClean, cacheDirty, cacheEmpty
12 };
13 cacheStatem_State;
14 UINT m_hits;
15
16 IDX m_idx;
17 DATA* m_pData;
18
19 CacheEntry() { m_State=cacheEmpty; VERIFY(m_pData=new DATA); m_hits=0; }
20 virtual ~CacheEntry() { delete m_pData; }
21 };
22 typedef CMap<IDX,ARGIDX,CacheEntry*,CacheEntry*> CCacheMap;
23 typedef CList<CacheEntry*,CacheEntry*> CCacheList;
24
25 CCacheList m_Cache;
26 CCacheMap m_Map;
27
28 CLRUCache(UINT cacheSize){
29 for(int tmp=0;tmp<cacheSize;tmp++){
30 CacheEntry* p = new CacheEntry;
31 m_Cache.AddTail(p);
32 }
33 }
34 virtual ~CLRUCache(){
35 Flush();
36 POSITION p = m_Cache.GetHeadPosition();
37 while(p){
38 CacheEntry* c = m_Cache.GetNext(p);
39 delete c;
40 }
41 }
42
43 DATA* GetCached(ARGIDX idx,BOOL bLoad=TRUE) {
44 CacheEntry* rv;
45 if(m_Map.Lookup(idx,rv)){
46 rv->m_hits++;
47 PopUp(rv);
48 return rv->m_pData;
49 }
50 if(!bLoad)
51 return NULL;
52 rv = m_Cache.GetTail();
53 ASSERT(rv);
54 switch(rv->m_State){
55 case CacheEntry::cacheDirty:
56 FlushEntry(rv);
57 case CacheEntry::cacheClean:
58 m_Map.RemoveKey(rv->m_idx);
59 rv->m_State=CacheEntry::cacheEmpty;
60 case CacheEntry::cacheEmpty:
61 break;
62 default:
63 ASSERT(FALSE);
64 }
65 if(!_ReadIn(idx,rv->m_pData))
66 return NULL;
67 rv->m_hits=1;
68 rv->m_State=CacheEntry::cacheClean;
69 rv->m_idx=idx;
70 m_Map[idx]=rv;
71 PopUp(rv);
72 return rv->m_pData;
73 }
74 BOOL MakeDirty(ARGIDX idx) {
75 CacheEntry* pEntry;
76 if(m_Map.Lookup(idx,pEntry)){
77 ASSERT(pEntry->m_State==CacheEntry::cacheClean || pEntry->m_State==CacheEntry::cacheDirty);
78 pEntry->m_State=CacheEntry::cacheDirty;
79 return TRUE;
80 }
81 return FALSE;
82 }
83 BOOL Flush() {
84 POSITION p = m_Cache.GetHeadPosition();
85 while(p){
86 CacheEntry* pEntry = m_Cache.GetNext(p);
87 ASSERT(pEntry);
88 FlushEntry(pEntry);
89 }
90 return TRUE;
91 }
92 BOOL FlushEntry(CacheEntry* pEntry) {
93 if(pEntry->m_State==CacheEntry::cacheDirty){
94 BOOL rv = _WriteOut(pEntry->m_idx,pEntry->m_pData);
95 if(rv)
96 pEntry->m_State=CacheEntry::cacheClean;
97 }
98 return FALSE;
99 }
100 void PopUp(CacheEntry* pEntry) {
101 POSITION p = m_Cache.Find(pEntry);
102 ASSERT(p);
103 m_Cache.RemoveAt(p);
104 VERIFY(m_Cache.AddHead(pEntry));
105 }
106
107 virtualBOOL _ReadIn(ARGIDX idx,DATA* data) = 0;
108 virtual BOOL _WriteOut(ARGIDX idx,DATA* data) = 0;
109};
110
111};
112
113 #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 @@
1#include "../stdafx.h"
2#include "RegEx.h"
3
4 #defineisWordableChar(c) (isalnum(c) || (c)=='_')
5
6BOOL CRegEx::Compile(LPCTSTR regex,int flags)
7{
8 ASSERT(!((flags&regExtended) && (flags&regLiteral)));
9 m_Matches.RemoveAll();
10 m_Strip.RemoveAll();
11 m_Strip.SetSize(0,15);
12 m_Pattern=regex;
13 m_ParsePointer=0;
14 m_Error=0;
15 m_Sets.RemoveAll();
16 m_Flags=flags;
17 m_iFlags=0;
18 m_BOLs=m_EOLs=0;
19 m_Subexps = 0;
20 m_Categories=1;// 0 is 'everything else'
21 m_bBackRefs=FALSE;
22 memset(m_Category,0,sizeof(m_Category));
23
24 // Go ahead.
25 m_Error || m_Strip.Add(CSop(CSop::opEnd));
26 if(flags&regExtended){
27 ParseERE();
28 }else if(flags&regLiteral){
29 ParseLiteral();
30 }else{
31 ParseBRE();
32 }
33 m_Error || m_Strip.Add(CSop(CSop::opEnd));
34 Categorize();
35 m_Strip.FreeExtra();
36 FigureMust();
37 m_Pluses=CountPluses();
38 if(m_iFlags&iflagsBad){
39 m_Error || (m_Error=regeAssert);
40 // ??? point to nuls? ;-)
41 }
42 // We may wish to free some memory here if we're erroneous (ie. m_Error..)
43 m_ParseParens.RemoveAll();
44#ifdef _DEBUG
45 if(m_Error){
46 CString tmp;
47 tmp.Format("RE: ParseError: %d\n",m_Error);
48 TRACE0(tmp);
49 }
50 //DumpStrip(afxDump);
51#endif
52 return (m_bCompiled=(!m_Error));
53}
54
55BOOL CRegEx::Match(LPCTSTR src,int flags)
56{
57 if(!m_bCompiled)
58 return FALSE;
59 if(m_iFlags&iflagsBad)
60 return FALSE;
61 m_Input=src;
62 m_mFlags=flags;
63 m_mPointer=m_Input;
64 m_mBegin=m_Input;
65 m_mEnd=&m_mBegin[m_Input.GetLength()];
66 ASSERT(m_mPointer<=m_mEnd);
67 m_Matches.RemoveAll();
68 if(!m_Must.IsEmpty()){
69 if(m_Input.Find(m_Must)<0)
70 return FALSE;
71 }
72 // Go ahead..
73int stripLen = m_Strip.GetSize();
74 m_mLastPos.SetSize(0);
75 for(int tmp=0;tmp<stripLen;tmp++)
76 m_Strip[tmp].m_MatchData=0;
77LPCTSTR beginp = m_mBegin;
78LPCTSTR endp;
79 for(;;){
80 endp = MatchFast(beginp);
81 if(!endp)
82 return FALSE;
83 if((m_mFlags&regNoSubExpressions) && !m_bBackRefs)
84 break;
85 ASSERT(m_cOldP);
86 for(;;){
87 endp = MatchSlow(m_cOldP,m_mEnd,1,stripLen-1);
88 if(endp)
89 break;
90 ASSERT(m_cOldP<m_mEnd);
91 m_cOldP++;
92 }
93 if((m_mFlags&regOneMatch) && !m_bBackRefs)
94 break;
95 // Oh, his, we want the subexpression..
96 m_Matches.SetSize(m_Subexps+1);
97 LPCTSTR dp;
98 if(!m_bBackRefs && !(m_mFlags&regBackRefs)){
99 dp = MatchDissect(m_cOldP,endp,1,stripLen-1);
100 }else{
101 if(m_Pluses>0 && !m_mLastPos.GetSize())
102 m_mLastPos.SetSize(m_Pluses);
103 dp = MatchBackRef(m_cOldP,endp,1,stripLen-1,0);
104 }
105 if(dp)
106 break;
107 // Uh.. oh.. we couldn't find a subexpression-level match
108 ASSERT(m_bBackRefs);
109 ASSERT(m_Pluses==0 || m_mLastPos.GetSize());
110 for(;;){
111 if(dp || endp <= m_cOldP)
112 break;// defeat.. ?
113 endp = MatchSlow(m_cOldP,endp-1,1,stripLen-1);
114 if(!endp)
115 break;// defeat.. ?
116 // Try it on a shorter possibility..
117#ifdef _DEBUG
118 for(tmp=1;tmp<=m_Subexps;tmp++)
119 ASSERT(m_Matches[tmp].m_Begin<0 && m_Matches[tmp].m_End<0);
120#endif
121 dp = MatchBackRef(m_cOldP,endp,1,stripLen-1,0);
122 }
123 ASSERT((!dp) || dp==endp);
124 if(dp)// Found a shorter one..
125 break;
126 // Despite initial appearances, there is no match here
127 beginp = m_cOldP+1;
128 ASSERT(beginp<=m_mEnd);
129 }
130 // Fill in the detail if so requested..
131 if(!(m_mFlags&regNoSubExpressions)){
132 if(!m_Matches.GetSize())
133 m_Matches.SetSize(1);
134 m_Matches[0].m_Begin=m_cOldP-m_mBegin;
135 m_Matches[0].m_End=endp-m_mBegin;
136 }
137 m_mLastPos.RemoveAll();
138 return TRUE;
139}
140
141CString CRegEx::Replace(LPCTSTR src,LPCTSTR rep,int flags)
142{
143 // ***
144 return CString();
145}
146
147void CRegEx::ParseERE(int stop)
148{
149UCHAR c;
150BOOL first=TRUE;
151int prevF, prevB;
152 for(;;){
153 int co = m_Strip.GetSize();
154 while(m_ParsePointer < m_Pattern.GetLength() && ((c=m_Pattern[m_ParsePointer])!='|') && c!=stop)
155 ParseEREexp();
156 if(m_Strip.GetSize()==co){
157 m_Error || (m_Error=regeEmpty);
158 // ??? point to nuls?
159 }
160 if(m_ParsePointer>=m_Pattern.GetLength() || m_Pattern[m_ParsePointer]!='|')
161 break;
162 else
163 m_ParsePointer++;
164 if(first){
165 StripInsert(co,CSop(CSop::opChoice0,m_Strip.GetSize()-co+1));
166 prevF = prevB = co;
167 first=FALSE;
168 }
169 m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-prevB));
170 prevB = m_Strip.GetSize()-1;
171 m_Error || (m_Strip[prevF].m_Operand=m_Strip.GetSize()-prevF);
172 prevF = m_Strip.GetSize();
173 m_Error || m_Strip.Add(CSop(CSop::opOr1,0));// offset isn't really right.. very so..
174 }
175 if(!first){
176 m_Error || (m_Strip[prevF].m_Operand=m_Strip.GetSize()-prevF);
177 m_Error || m_Strip.Add(CSop(CSop::opChoice1,m_Strip.GetSize()-prevB));
178 }
179 ASSERT(m_ParsePointer >= m_Pattern.GetLength() || m_Pattern[m_ParsePointer]==stop);
180}
181
182void CRegEx::ParseEREexp()
183{
184 ASSERT(m_ParsePointer < m_Pattern.GetLength());
185UCHAR c = m_Pattern[m_ParsePointer++];
186int pos = m_Strip.GetSize();
187int subno;
188int count, count2;
189BOOL wascaret=FALSE;
190 switch(c){
191 case '(':
192 if(!(m_ParsePointer<m_Pattern.GetLength())){
193 TRACE0("RE: '(' at the end of the pattern\n");
194 if(!m_Error)
195 m_Error = regeParen;
196 // ??? point to nuls?
197 }
198 m_Subexps++;
199 subno=m_Subexps;
200 m_ParseParens.SetAtGrow(m_Subexps,CParenthesis(m_Strip.GetSize()));
201 m_Error || m_Strip.Add(CSop(CSop::opLeftParen,subno));
202 if(m_ParsePointer>=m_Pattern.GetLength() || m_Pattern[m_ParsePointer]!=')')
203 ParseERE(')');
204 VERIFY(m_ParseParens[m_Subexps].m_End = m_Strip.GetSize());
205 m_Error || m_Strip.Add(CSop(CSop::opRightParen,subno));
206 if(m_ParsePointer >= m_Pattern.GetLength() || m_Pattern[m_ParsePointer++]!=')'){
207 TRACE0("RE: No matching ')'\n");
208 if(!m_Error)
209 m_Error = regeParen;
210 // ??? point to nuls?
211 }
212 break;
213 case '^':
214 m_Error || m_Strip.Add(CSop(CSop::opBOL));
215 m_iFlags|=iflagsUseBOL;
216 m_BOLs++;
217 wascaret=TRUE;
218 break;
219 case '$':
220 m_Error || m_Strip.Add(CSop(CSop::opEOL));
221 m_iFlags|=iflagsUseEOL;
222 m_EOLs++;
223 break;
224 case '|':
225 TRACE0("RE: '|' outside of expression\n");
226 if(!m_Error)
227 m_Error = regeEmpty;
228 // ??? point to nuls?
229 break;
230 case '*':
231 case '+':
232 case '?':
233 TRACE0("RE: '*'/'+'/'?' with no previous expression\n");
234 if(!m_Error)
235 m_Error = regeBadRepeat;
236 // ??? point to nuls?
237 break;
238 case '.':
239 if(m_Flags&regNewLine)
240 EmitNonNewLineAny();
241 else
242 m_Error || m_Strip.Add(CSop(CSop::opAny));
243 break;
244 case '[':
245 ParseBracket();
246 break;
247 case '\\':
248 if(m_ParsePointer >= m_Pattern.GetLength()){
249 TRACE0("RE: '\\' at the end of the pattern\n");
250 if(!m_Error)
251 m_Error = regeEscape;
252 // ??? point to nuls?
253 }else{
254 c = m_Pattern[m_ParsePointer++];
255 EmitOrdinary(c);
256 }
257 break;
258 case '{':
259 if(m_ParsePointer >= m_Pattern.GetLength() || !isdigit(m_Pattern[m_ParsePointer])){
260 TRACE0("RE: '{' with no repeat count\n");
261 if(!m_Error)
262 m_Error = regeBadRepeat;
263 // ??? point to nuls?
264 }
265 // Fallthrough..
266 default:
267 EmitOrdinary(c);
268 break;
269 }
270 if(m_ParsePointer >= m_Pattern.GetLength())
271 return;
272 c = m_Pattern[m_ParsePointer];
273 // Call a '{' repetition if followed by a digit
274 if (!(c=='*' || c=='+' || c=='?' || ( c=='{' && (m_ParsePointer+1) < m_Pattern.GetLength() && isdigit(m_Pattern[m_ParsePointer+1])) ))
275 return; // No repetitor - done.
276 m_ParsePointer++;
277 if(wascaret){
278 TRACE0("RE: repetitive '^' detected\n");
279 if(!m_Error)
280 m_Error = regeBadRepeat;
281 // ??? point to nuls?
282 }
283 switch(c){
284 case '*':// Implemeted as +?
285 // + expression
286 StripInsert(pos,CSop(CSop::opPlus0,m_Strip.GetSize()-pos+1));
287 m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
288 // ? expression
289 StripInsert(pos,CSop(CSop::opQuest0,m_Strip.GetSize()-pos+1));
290 m_Error || m_Strip.Add(CSop(CSop::opQuest1,m_Strip.GetSize()-pos));
291 break;
292 case '+':
293 // + expression
294 StripInsert(pos,CSop(CSop::opPlus0,m_Strip.GetSize()-pos+1));
295 m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
296 break;
297 case '?':
298 // Kludge - emit y? as (y|) until subtle bug gets fixed :-)
299 StripInsert(pos,CSop(CSop::opChoice0,m_Strip.GetSize()-pos+1));
300 m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-pos));
301 m_Error || (m_Strip[pos].m_Operand=m_Strip.GetSize()-pos);
302 m_Error || m_Strip.Add(CSop(CSop::opOr1,1));
303 m_Error || m_Strip.Add(CSop(CSop::opChoice1,2));
304 break;
305 case '{':
306 count = ParseCount();
307 if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]==','){
308 m_ParsePointer++;
309 if(isdigit(m_Pattern[m_ParsePointer])){ // HHH Personally, I doubt it is always available
310 count2=ParseCount();
311 if(!(count<=count2)){
312 TRACE0("RE: Disbalanced counts in '{}' repeater\n");
313 m_Error || (m_Error=regeBadBrace);
314 // ??? point to nuls?
315 }
316 }else // Single number with comma
317 count2=256; // Infinity
318 }else // Single number
319 count2=count;
320 EmitRepeat(pos,count,count2);
321 if(m_ParsePointer >= m_Pattern.GetLength() || m_Pattern[m_ParsePointer]!='}'){
322 // No '}'..
323 TRACE0("RE: No immediately following '}' of '{' expression\n");
324 while(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]!='}')
325 m_ParsePointer++;
326 if(m_ParsePointer >= m_Pattern.GetLength()){
327 TRACE0("RE: No closing '}' found\n");
328 m_Error || (m_Error=regeBrace);
329 }else
330 m_Error || (m_Error=regeBadBrace);
331 // ??? point to nuls?
332 }else
333 m_ParsePointer++;
334 break;
335 }
336 if(m_ParsePointer >= m_Pattern.GetLength())
337 return;
338 c = m_Pattern[m_ParsePointer];
339 if(!(c=='*' || c=='+' || c=='?' || (c=='{' && (m_ParsePointer+1)<m_Pattern.GetLength() && isdigit(m_Pattern[m_ParsePointer+1]))))
340 return;
341 TRACE0("RE: Double repeater\n");
342 m_Error || (m_Error=regeBadRepeat);
343 // ??? point to nuls?
344}
345
346void CRegEx::StripInsert(int pos,CSop& sop)
347{
348 if(m_Error)
349 return;
350int sn = m_Strip.GetSize();
351 m_Strip.InsertAt(pos,sop);
352 for(int tmp=1;tmp<m_ParseParens.GetSize();tmp++){
353 if(m_ParseParens[tmp].m_Begin>=pos)
354 m_ParseParens[tmp].m_Begin++;
355 if(m_ParseParens[tmp].m_End>=pos)
356 m_ParseParens[tmp].m_End++;
357 }
358}
359
360void CRegEx::EmitOrdinary(UCHAR c)
361{
362 if(m_Flags&regIgnoreCase && isalpha(c) && (tolower(c) !=toupper(c))){
363 // Emit both cases
364 CString savePattern = m_Pattern;
365 int savePointer = m_ParsePointer;
366 m_Pattern=c;
367 m_Pattern+=']';
368 m_ParsePointer=0;
369 ParseBracket();
370 m_Pattern=savePattern;
371 m_ParsePointer=savePointer;
372 }else{
373 m_Error || m_Strip.Add(CSop(CSop::opChar,c));
374 if(!m_Category[(BYTE)c])
375 m_Category[(BYTE)c]=m_Categories++;
376 }
377}
378
379void CRegEx::EmitNonNewLineAny()
380{
381 // Kludges're going on and on..
382CString savePattern = m_Pattern;
383int savePointer = m_ParsePointer;
384 m_Pattern="^\n]";
385 m_ParsePointer=0;
386 ParseBracket();
387 m_Pattern=savePattern;
388 m_ParsePointer=savePointer;
389}
390
391int CRegEx::ParseCount()
392{
393BOOL nonEmpty=FALSE;
394int rv = 0;
395UCHAR c;
396 while(m_ParsePointer < m_Pattern.GetLength() && isdigit(c=m_Pattern[m_ParsePointer]) && rv <=255){
397 rv = rv*10 + c-'0';
398 nonEmpty=TRUE;
399 m_ParsePointer++;
400 }
401 if(rv>255 || !nonEmpty){
402 m_Error || (m_Error=regeBadBrace);
403 // ??? point to nuls?
404 }
405 return rv;
406}
407
408void CRegEx::ParseBracket()
409{
410 // Dept. of truly sickening special case kludges
411 if((m_ParsePointer+5) < m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,6).Compare("[:<]]")){
412 m_Error || m_Strip.Add(CSop(CSop::opBOW));
413 m_ParsePointer+=6;
414 return;
415 }
416 if((m_ParsePointer+5) < m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,6).Compare("[:>]]")){
417 m_Error || m_Strip.Add(CSop(CSop::opEOW));
418 m_ParsePointer+=6;
419 return;
420 }
421BOOL invert=TRUE;
422 if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='^')
423 m_ParsePointer++;
424 else
425 invert=FALSE;
426CSet cset;
427 if(m_ParsePointer < m_Pattern.GetLength()){
428 switch(m_Pattern[m_ParsePointer]){
429 case ']':
430 case '-':
431 cset.Add(m_Pattern[m_ParsePointer]);
432 m_ParsePointer++;
433 break;
434 }
435 }
436 while(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]!=']' && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("-]")))
437 ParseBracketTerm(cset);
438 if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='-'){
439 m_ParsePointer++;
440 cset.Add('-');
441 }
442 if(m_ParsePointer < m_Pattern.GetLength() && m_Pattern[m_ParsePointer]==']')
443 m_ParsePointer++;
444 else{
445 m_Error || (m_Error=regeBracket);
446 // ??? point to nuls?
447 return;
448 }
449 if(m_Flags&regIgnoreCase){
450 for(int tmp=CSet::size-1;tmp>=0;tmp--){
451 if(cset.IsIn(tmp) && isalpha(tmp) && (toupper(tmp)!=tolower(tmp)))
452 cset.Add(isupper(tmp)?tolower(tmp):toupper(tmp));
453 }
454 /*
455 if(!cset->m_Multis.IsEmpty())
456 cset.CollatingCase();
457 */
458 }
459 if(invert){
460 for(int tmp=CSet::size-1;tmp>=0;tmp--)
461 if(cset.IsIn(tmp))
462 cset.Sub(tmp);
463 else
464 cset.Add(tmp);
465 if(m_Flags&regNewLine)
466 cset.Sub('\n');
467 /*
468 if(!cset.m_Multis.IsEmpty())
469 cset.CollatingInvert();
470 */
471 }
472UCHAR c = cset.GetOnly();
473 if(c){
474 EmitOrdinary(c);
475 }else
476 m_Error || m_Strip.Add(CSop(CSop::opAnyOf,StoreSet(cset)));
477}
478
479void CRegEx::CSet::Add(UCHAR c)
480{
481 m_Set[(BYTE)c]=TRUE;
482 m_Hash+=c;
483}
484
485BOOL CRegEx::CSet::IsIn(UCHAR c)
486{
487 return m_Set[(BYTE)c];
488}
489
490void CRegEx::CSet::Sub(UCHAR c)
491{
492 m_Set[(BYTE)c]=FALSE;
493 m_Hash-=c;
494}
495
496UCHAR CRegEx::CSet::GetOnly()
497{
498int rv = 0;
499UCHAR only = 0;
500 for(int tmp=0;tmp<size;tmp++){
501 rv+=m_Set[tmp]?(only=tmp,1):0;
502 }
503 return (rv==1)?only:0;
504}
505
506int CRegEx::StoreSet(CSet& cset)
507{
508 for(int tmp=0;tmp<m_Sets.GetSize();tmp++)
509 if(m_Sets[tmp]==cset)
510 return tmp;
511 return m_Sets.Add(cset);
512}
513
514void CRegEx::ParseBracketTerm(CSet& cset)
515{
516UCHAR c;
517 switch((m_ParsePointer<m_Pattern.GetLength())?m_Pattern[m_ParsePointer]:0){
518 case '[':
519 c = ((m_ParsePointer+1)<m_Pattern.GetLength())?m_Pattern[m_ParsePointer+1]:0;
520 break;
521 case '-':
522 m_Error || (m_Error=regeRange);
523 // ??? point to nuls?
524 return;
525 default:
526 c = 0;
527 break;
528 }
529 switch(c){
530 case ':':// Character class
531 m_ParsePointer+=2;
532 if(m_ParsePointer>=m_Pattern.GetLength()){
533 m_Error || (m_Error=regeBracket);
534 // ??? point to nuls?
535 }
536 c = m_Pattern[m_ParsePointer];
537 if(c== '-' || c==']'){
538 m_Error || (m_Error=regeCType);
539 // ??? point to nuls?
540 }
541 ParseBracketCClass(cset);
542 if(m_ParsePointer>=m_Pattern.GetLength()){
543 m_Error || (m_Error=regeBracket);
544 // ??? point to nuls?
545 }
546 if((m_ParsePointer+1)>=m_Pattern.GetLength() || (m_Pattern.Mid(m_ParsePointer,2).Compare(":]"))){
547 m_Error || (m_Error=regeCType);
548 // ??? point to nuls?
549 }else
550 m_ParsePointer+=2;
551 break;
552 case '=':// Equivalence class
553 m_ParsePointer+=2;
554 if(m_ParsePointer >= m_Pattern.GetLength()){
555 m_Error || (m_Error=regeBracket);
556 // ??? point to nuls?
557 }
558 c = m_Pattern[m_ParsePointer];
559 if(c== '-' || c==']'){
560 m_Error || (m_Error=regeCollate);
561 // ??? point to nuls?
562 }
563 ParseBracketEClass(cset);
564 if((m_ParsePointer+1)>=m_Pattern.GetLength() || (m_Pattern.Mid(m_ParsePointer,2).Compare("=]"))){
565 m_Error || (m_Error=regeCollate);
566 // ??? point to nuls?
567 }else
568 m_ParsePointer+=2;
569 break;
570 default:// Symbol, character or range
571 {
572 UCHAR start, finish;
573 start = ParseBracketSymbol();
574 if((m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='-') /*&& (m_ParsePointer+1)<m_Pattern.GetLength() && m_Pattern[m_ParsePointer+1]==']'*/){
575 // I believe the expression above is seetwo..
576 // range.
577 m_ParsePointer++;
578 if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='-'){
579 m_ParsePointer++;
580 finish='-';
581 }else
582 finish=ParseBracketSymbol();
583 }else
584 finish=start;
585 if(((BYTE)start)>((BYTE)finish)){
586 m_Error || (m_Error=regeRange);
587 // ??? point to nuls?
588 }
589 for(int tmp=start;tmp<=(BYTE)finish;tmp++)
590 cset.Add(tmp);
591 }
592 break;
593 }
594}
595
596void CRegEx::ParseBracketCClass(CSet& cset)
597{
598 static struct{
599 char *className;
600 char *classChars;
601 }cc[] = {
602 {"alnum","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
603 {"alpha","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
604 {"blank"," \t"},
605 {"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"},
606 {"digit","0123456789"},
607 {"graph","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"},
608 {"lower","abcdefghijklmnopqrstuvwxyz"},
609 {"print","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ "},
610 {"punct","!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"},
611 {"space","\t\n\v\f\r "},
612 {"upper","ABCDEFGHIJKLMNOPQRSTUVWXYZ"},
613 {"xdigit","0123456789ABCDEFabcdef"}
614};
615CString cclass;
616UCHAR c;
617 while(m_ParsePointer < m_Pattern.GetLength() && isalpha(c=m_Pattern[m_ParsePointer])){
618 cclass+=c;
619 m_ParsePointer++;
620 }
621char *classChars = NULL;
622 for(int tmp=0;tmp<(sizeof(cc)/sizeof(cc[0]));tmp++){
623 if(!cclass.CompareNoCase(cc[tmp].className)){
624 classChars=cc[tmp].classChars;
625 break;
626 }
627 }
628 if(!classChars){
629 m_Error || (m_Error=regeCType);
630 // ??? point to nuls?
631 return;
632 }
633 while(*classChars)
634 cset.Add(*(classChars++));
635 // --- multis
636}
637
638void CRegEx::ParseBracketEClass(CSet& cset)
639{
640 cset.Add(ParseBracketCollatingElement('='));;
641}
642
643UCHAR CRegEx::ParseBracketCollatingElement(UCHAR term)
644{
645 static struct{
646 char *entityName;
647 char entity;
648 }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'} };
649CString seeTwo;
650 seeTwo=term;
651 seeTwo+=']';
652CString entityName;
653 while(m_ParsePointer<m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare(seeTwo)))
654 entityName+=m_Pattern[m_ParsePointer++];
655 if(m_ParsePointer>=m_Pattern.GetLength()){
656 m_Error || (m_Error=regeBracket);
657 // ??? point to nuls?
658 return 0;
659 }
660 for(int tmp=0;tmp<(sizeof(cc)/sizeof(cc[0]));tmp++)
661 if(!entityName.CompareNoCase(cc[tmp].entityName))
662 return cc[tmp].entity;
663 if(entityName.GetLength()==1)
664 return entityName[0];
665 m_Error || (m_Error=regeCollate);
666 // ??? point to nuls?
667 return 0;
668}
669
670UCHAR CRegEx::ParseBracketSymbol()
671{
672 if(m_ParsePointer>=m_Pattern.GetLength()){
673 m_Error || (m_Error=regeBracket);
674 // ??? point to nuls?
675 }
676 if((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("[."))
677 m_ParsePointer+=2;
678 else
679 return m_Pattern[m_ParsePointer++];
680 // Collating symbol
681UCHAR rv = ParseBracketCollatingElement('.');
682 if((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("[."))
683 m_ParsePointer+=2;
684 else{
685 m_Error || (m_Error=regeCollate);
686 // ??? point to nuls?
687 }
688 return rv;
689}
690
691void CRegEx::EmitRepeat(int pos,int from,int to)
692{
693 if(m_Error)
694 return;
695 ASSERT(from<=to);
696int finish = m_Strip.GetSize();
697int copy;
698 #defineN 2
699#define INF 3
700#define REP(f,t) ((f)*8+(t))
701#define MAP(n) (((n)<=1)?(n):((n)==256)?INF:N)
702 switch(REP(MAP(from),MAP(to))){
703 case REP(0,0):// must be user doing ths??
704 m_Strip.SetSize(pos);
705 break;
706 case REP(0,1):// as in '?'
707 case REP(0,N):// as in '{1,n}?'
708 case REP(0,INF):// as in '{1,}?'
709 // Kludge - emit y? as (y|) until something gets fixed..
710 StripInsert(pos,CSop(CSop::opChoice0,pos));
711 EmitRepeat(pos+1,1,to);
712 m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-pos));
713 m_Error || (m_Strip[pos].m_Operand=m_Strip.GetSize()-pos);
714 m_Error || m_Strip.Add(CSop(CSop::opOr1,1));
715 m_Error || m_Strip.Add(CSop(CSop::opChoice1,2));
716 break;
717 case REP(1,1):
718 break;
719 case REP(1,N):// as in 'x?x{1,n-1}'
720 // Kludge again..
721 StripInsert(pos,CSop(CSop::opChoice0,pos));
722 m_Error || m_Strip.Add(CSop(CSop::opOr0,m_Strip.GetSize()-pos));
723 m_Error || (m_Strip[pos].m_Operand=m_Strip.GetSize()-pos);
724 m_Error || m_Strip.Add(CSop(CSop::opOr1,1));
725 m_Error || m_Strip.Add(CSop(CSop::opChoice1,2));
726 copy = StripDuplicate(pos+1,finish+1);
727 ASSERT(copy==(finish+4));
728 EmitRepeat(copy,1,to-1);
729 break;
730 case REP(1,INF): // as in '+'
731 StripInsert(pos,CSop(CSop::opPlus0,pos));
732 m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
733 break;
734 case REP(N,N):// as in 'xx{from-1,to-1}'
735 copy = StripDuplicate(pos,finish);
736 EmitRepeat(copy,from-1,to-1);
737 break;
738 case REP(N,INF): // as in 'xx{n-1,}'
739 copy = StripDuplicate(pos,finish);
740 EmitRepeat(copy,from-1,to);
741 break;
742#ifndef NDEBUG
743 default:
744 ASSERT(FALSE);
745 break;
746#endif
747 }
748#undef MAP
749#undef REP
750#undef INF
751#undef N
752}
753
754int CRegEx::StripDuplicate(int from,int to)
755{
756int rv = m_Strip.GetSize();
757 ASSERT(from<=to);
758 if(from==to)
759 return rv;
760 // Maybe should be optimized for copying the whole thing.
761 for(int tmp=from;tmp<to;tmp++)
762 m_Strip.Add(m_Strip[tmp]);
763 return rv;
764}
765
766void CRegEx::Categorize()
767{
768 if(m_Error)
769 return;
770 for(int tmp=0;tmp<(sizeof(m_Category)/sizeof(m_Category[0]));tmp++)
771 if((!m_Category[tmp]) && IsInSets(tmp)){
772 int cat = m_Categories++;
773 m_Category[tmp]=cat;
774 for(int c=tmp+1;c<(sizeof(m_Category)/sizeof(m_Category[0]));c++)
775 if((!m_Category[c]) && IsInSameSets(tmp,c))
776 m_Category[c]=cat;
777 }
778}
779
780BOOL CRegEx::IsInSets(UCHAR c)
781{
782 for(int tmp=0;tmp<m_Sets.GetSize();tmp++)
783 if(m_Sets[tmp].IsIn(c))
784 return TRUE;
785 return FALSE;
786}
787
788BOOL CRegEx::IsInSameSets(UCHAR c1,UCHAR c2)
789{
790 for(int tmp=0;tmp<m_Sets.GetSize();tmp++)
791 if(m_Sets[tmp].IsIn(c1)!=m_Sets[tmp].IsIn(c2))
792 return FALSE;
793 return TRUE;
794}
795
796void CRegEx::FigureMust()
797{
798 if(m_Error)
799 return;
800 m_Must.Empty();
801int stripLen = m_Strip.GetSize();
802int seqStart, seqLength = 0;
803int mustStart, mustLength = 0;
804 for(int tmp=1;tmp<stripLen;tmp++){
805 switch(m_Strip[tmp].m_Operator){
806 case CSop::opChar:
807 if(!seqLength)
808 seqStart=tmp;
809 seqLength++;
810 break;
811 case CSop::opPlus0:
812 case CSop::opLeftParen:
813 case CSop::opRightParen:
814 break;// Break, since they don't break the sequence
815 case CSop::opQuest0:
816 case CSop::opChoice0:
817 // These ones we skip.
818 do{
819 tmp+=m_Strip[tmp].m_Operand;
820 // I still think it could be ASSERTed..
821 if(m_Strip[tmp].m_Operator!=CSop::opQuest1 && m_Strip[tmp].m_Operator!=CSop::opChoice1 && m_Strip[tmp].m_Operator!=CSop::opOr1){
822 m_iFlags|=iflagsBad;
823 return;
824 }
825 }while(m_Strip[tmp].m_Operator!=CSop::opQuest1 && m_Strip[tmp].m_Operator!=CSop::opChoice1);
826 // Fallthrough..
827 default:
828 // End of sequence
829 if(seqLength>mustLength){
830 mustStart=seqStart;
831 mustLength=seqLength;
832 }
833 seqLength=0;
834 break;
835 }
836 }// Hmm.. originally it's meant to be do while not opEnd..
837 if(!mustLength)
838 return;
839 // Turn into string, but, wait, personally I'm sure it could be put in the main loop.. or maybe not..
840 for(tmp=0;tmp<seqLength;tmp++){
841 while(m_Strip[seqStart+tmp].m_Operator!=CSop::opChar)
842 ASSERT(tmp<seqLength);
843 m_Must+=m_Strip[tmp].m_Operand;
844 }
845}
846
847int CRegEx::CountPluses()
848{
849 if(m_Error)
850 return 0;
851int stripLen = m_Strip.GetSize();
852int rv = 0;
853int nest = 0;
854 for(int tmp=0;tmp<stripLen;tmp++){
855 switch(m_Strip[tmp].m_Operator){
856 case CSop::opPlus0:
857 nest++;
858 break;
859 case CSop::opPlus1:
860 if(nest>rv)
861 rv = nest;
862 nest--;
863 break;
864 }
865 }// Again, originally we were supposed to scan till opEnd..
866 if(nest)
867 m_iFlags|=iflagsBad;// Could this be an ASSERTion?
868 return rv;
869}
870
871void CRegEx::ParseLiteral()
872{
873 if(!m_Pattern.GetLength()){
874 m_Error || (m_Error=regeEmpty);
875 // ??? point to nuls?
876 }
877 while(m_ParsePointer < m_Pattern.GetLength())
878 EmitOrdinary(m_Pattern[m_ParsePointer++]);
879}
880
881void CRegEx::ParseBRE(int stopa,int stopb)
882{
883int start = m_Strip.GetSize();
884BOOL first=TRUE;
885BOOL wasDollar=FALSE;
886 if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='^'){
887 m_ParsePointer++;
888 m_Error || m_Strip.Add(CSop(CSop::opBOL,0));
889 m_iFlags|=iflagsUseBOL;
890 m_BOLs++;
891 }
892CString stopstr;
893 if(stopa){
894 stopstr+=stopa;
895 if(stopb)
896 stopstr+=stopb;
897 }
898 while(m_ParsePointer < m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare(stopstr))){
899 wasDollar = ParseBREexp(first);
900 first=FALSE;
901 }
902 if(wasDollar){// Trailing anchor that was..
903 m_Strip.SetSize(m_Strip.GetSize()-1);
904 m_Error || m_Strip.Add(CSop(CSop::opEOL,0));
905 m_iFlags|=iflagsUseEOL;
906 m_EOLs++;
907 }
908 if(m_Strip.GetSize()==start){
909 m_Error || (m_Error=regeEmpty);
910 // ??? point to nuls?
911 }
912}
913
914BOOL CRegEx::ParseBREexp(BOOL ordinaryStar)
915{
916int subno;
917int pos = m_Strip.GetSize();
918 ASSERT(m_ParsePointer<m_Pattern.GetLength());
919int c = m_Pattern[m_ParsePointer++];
920 if(c=='\\'){
921 if(m_ParsePointer>=m_Pattern.GetLength()){
922 m_Error || (m_Error=regeEscape);
923 // ??? point to nuls
924 }else
925 c = 0x100|m_Pattern[m_ParsePointer++];
926 }
927 switch(c){
928 case '.':
929 if(m_Flags&regNewLine)
930 EmitNonNewLineAny();
931 else
932 m_Error || m_Strip.Add(CSop(CSop::opAny,0));
933 break;
934 case '[':
935 ParseBracket();
936 break;
937 case 0x100|'{':
938 m_Error || (m_Error=regeBadRepeat);
939 // ??? point to nuls?
940 break;
941 case 0x100|'(':
942 m_Subexps++;
943 subno=m_Subexps;
944 m_ParseParens.SetAtGrow(m_Subexps,CParenthesis(m_Strip.GetSize()));
945 m_Error || m_Strip.Add(CSop(CSop::opLeftParen,subno));
946 if(m_ParsePointer<m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\)")))
947 ParseBRE('\\',')');
948 VERIFY(m_ParseParens[m_Subexps].m_End = m_Strip.GetSize());
949 m_Error || m_Strip.Add(CSop(CSop::opRightParen,subno));
950 if((m_ParsePointer+1) < m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\)"))
951 m_ParsePointer+=2;
952 else{
953 m_Error || (m_Error=regeParen);
954 // ??? point to nuls?
955 }
956 break;
957 case 0x100|')':
958 case 0x100|'}':
959 // Can this possibly happen?!
960 m_Error || (m_Error=regeParen);
961 // ??? point to nuls?
962 break;
963 case 0x100|'1':
964 case 0x100|'2':
965 case 0x100|'3':
966 case 0x100|'4':
967 case 0x100|'5':
968 case 0x100|'6':
969 case 0x100|'7':
970 case 0x100|'8':
971 case 0x100|'9':
972 {
973 int i = (c&0xFF)-'0';
974 if(i < m_ParseParens.GetSize() && m_ParseParens[i].m_End){
975 m_Error || m_Strip.Add(CSop(CSop::opBackRef0,i));
976 ASSERT(m_ParseParens[i].m_Begin);
977 ASSERT(m_Strip[m_ParseParens[i].m_Begin].m_Operator==CSop::opLeftParen);
978 ASSERT(m_Strip[m_ParseParens[i].m_End].m_Operator==CSop::opRightParen);
979 StripDuplicate(m_ParseParens[i].m_Begin+1,m_ParseParens[i].m_End);
980 m_Error || m_Strip.Add(CSop(CSop::opBackRef1,i));
981 }else{
982 m_Error || (m_Error=regeSubReg);
983 // ??? point to nuls?
984 }
985 m_bBackRefs=TRUE;
986 }
987 break;
988 case '*':
989 if(!ordinaryStar){
990 m_Error || (m_Error=regeBadRepeat);
991 // ??? point to nuls?
992 }
993 // Fallthrough..
994 default:
995 EmitOrdinary(c&0xFF);
996 break;
997 }
998 if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]=='*'){
999 m_ParsePointer++;
1000 // as in '+?'
1001 StripInsert(pos,CSop(CSop::opPlus0,m_Strip.GetSize()-pos+1));
1002 m_Error || m_Strip.Add(CSop(CSop::opPlus1,m_Strip.GetSize()-pos));
1003 StripInsert(pos,CSop(CSop::opQuest0,m_Strip.GetSize()-pos+1));
1004 m_Error || m_Strip.Add(CSop(CSop::opQuest1,m_Strip.GetSize()-pos));
1005 }else if ((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\{")){
1006 m_ParsePointer+=2;
1007 int count = ParseCount();
1008 int count2;
1009 if(m_ParsePointer<m_Pattern.GetLength() && m_Pattern[m_ParsePointer]==','){
1010 m_ParsePointer++;
1011 if(m_ParsePointer<m_Pattern.GetLength() && isdigit(m_Pattern[m_ParsePointer])){
1012 count2=ParseCount();
1013 if(count>count2){
1014 m_Error || (m_Error=regeBadBrace);
1015 // ??? poin to nuls?
1016 }
1017 }else // Single number with comma
1018 count2=256;
1019 }else // Single number
1020 count2=count;
1021 EmitRepeat(pos,count,count2);
1022 if((m_ParsePointer+1)>=m_Pattern.GetLength() || m_Pattern.Mid(m_ParsePointer,2).Compare("\\}")){
1023 while(m_ParsePointer<m_Pattern.GetLength() && !((m_ParsePointer+1)<m_Pattern.GetLength() && !m_Pattern.Mid(m_ParsePointer,2).Compare("\\}")))
1024 m_ParsePointer++;
1025 if(m_ParsePointer>=m_Pattern.GetLength()){
1026 m_Error || (m_Error=regeBrace);
1027 // ??? point to nuls?
1028 }
1029 m_Error || (m_Error=regeBadBrace);
1030 }else
1031 m_ParsePointer+=2;
1032 }else if(c=='$')
1033 return TRUE;
1034 return FALSE;
1035}
1036
1037CRegEx::CRegEx()
1038{
1039 m_bCompiled=FALSE;
1040}
1041
1042LPCTSTR CRegEx::MatchFast(LPCTSTR begin)
1043{
1044 MatchStatesClear(CSop::stCurrent);
1045 m_Strip[1].m_MatchData|=CSop::stCurrent;
1046int stripLen = m_Strip.GetSize();
1047 MatchStep(1,stripLen-1,CSop::stCurrent,charNothing,CSop::stCurrent);
1048 MatchStatesCopy(CSop::stFresh,CSop::stCurrent);
1049LPCTSTR coldp = NULL;
1050LPCTSTR p = begin;
1051int c = (begin==m_mBegin)?charOut:((int)(BYTE)m_mPointer[-1]);
1052 for(;;){
1053 // next character..
1054 int lastc = c;
1055 c = (p==m_mEnd)?charOut:(int)*(BYTE*)p;
1056 if(MatchStatesEqual(CSop::stCurrent,CSop::stFresh))
1057 coldp=p;
1058 // Is there an EOL and/or BOL between lastc and c? - they ask..
1059 intflagc=0;
1060 inti = 0;
1061 if((lastc=='\n' && m_Flags&regNewLine) || (lastc==charOut && !(m_mFlags&regNotBOL))){
1062 flagc=charBOL;
1063 i=m_BOLs;
1064 }
1065 if((c=='\n' && m_Flags&regNewLine) || (c==charOut && !(m_mFlags&regNotEOL))){
1066 flagc=(flagc==charBOL)?charBOLEOL:charEOL;
1067 i+=m_EOLs;
1068 }
1069 if(i){
1070 for(;i>0;i--)
1071 MatchStep(1,stripLen-1,CSop::stCurrent,flagc,CSop::stCurrent);
1072 }
1073 // What about a word boundary? - they wonder..
1074 if((flagc==charBOL || (lastc!=charOut && !isWordableChar(c))) && (c!=charOut && isWordableChar(c)))
1075 flagc = charBOW;
1076 if((lastc!=charOut && isWordableChar(lastc)) && (flagc==charEOL || (c!=charOut && !isWordableChar(c))))
1077 flagc = charEOW;
1078 if(flagc==charBOW || flagc==charEOW){
1079 MatchStep(1,stripLen-1,CSop::stCurrent,flagc,CSop::stCurrent);
1080 }
1081 // Are we done? Now WE wonder..
1082 if((m_Strip[stripLen-1].m_MatchData&CSop::stCurrent) || p==m_mEnd)
1083 break;// They insist I need to note break out.. Okay, I do..
1084 // Nope, we're not done. We have to face this character..
1085 MatchStatesCopy(CSop::stTemp,CSop::stCurrent);
1086 MatchStatesCopy(CSop::stCurrent,CSop::stFresh);
1087 ASSERT(c!=charOut);
1088 MatchStep(1,stripLen-1,CSop::stTemp,c,CSop::stCurrent);
1089 p++;
1090 }
1091 ASSERT(coldp);
1092 m_cOldP=coldp;// *** I believe this variable can be changed 'in-place'
1093 if(m_Strip[stripLen-1].m_MatchData&CSop::stCurrent)
1094 return &p[1];
1095 else
1096 return NULL;
1097}
1098
1099void CRegEx::MatchStatesClear(BYTE mask)
1100{
1101int stripLen = m_Strip.GetSize();
1102 for(int tmp=0;tmp<stripLen;tmp++)
1103 m_Strip[tmp].m_MatchData&=~mask;
1104}
1105
1106void CRegEx::MatchStep(int from,int to,BYTE maskBefore,int charCode,BYTE maskAfter)
1107{
1108BOOL i;
1109int look;
1110int here = from;
1111 for(int pc=from;pc!=to;pc++,here++){
1112 CSop s=m_Strip[pc];
1113 switch(s.m_Operator){
1114 case CSop::opEnd:
1115 ASSERT(pc==(to-1));
1116 break;
1117 case CSop::opChar:
1118 // Only characters can match..
1119 ASSERT((charCode<charOut) || charCode!=s.m_Operand);
1120 if(charCode==s.m_Operand)
1121 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1122 break;
1123 case CSop::opBOL:
1124 if(charCode==charBOL || charCode==charBOLEOL)
1125 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1126 break;
1127 case CSop::opEOL:
1128 if(charCode==charEOL || charCode==charBOLEOL)
1129 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1130 break;
1131 case CSop::opBOW:
1132 if(charCode==charBOW)
1133 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1134 break;
1135 case CSop::opEOW:
1136 if(charCode==charEOW)
1137 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1138 break;
1139 case CSop::opAny:
1140 if(charCode<charOut)
1141 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1142 break;
1143 case CSop::opAnyOf:
1144 if(charCode<charOut && m_Sets[s.m_Operand].m_Set[charCode])
1145 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskBefore)?maskAfter:0;
1146 break;
1147 case CSop::opBackRef0:// Ignored here..
1148 case CSop::opBackRef1:
1149 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1150 break;
1151 case CSop::opPlus0:
1152 // Forward, this is just an empty, comment says..
1153 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1154 break;
1155 case CSop::opPlus1:
1156 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1157 i =(m_Strip[here-s.m_Operand].m_MatchData&maskAfter)!=0;
1158 m_Strip[here-s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1159 if(!i && (m_Strip[here-s.m_Operand].m_MatchData&maskAfter)){
1160 // oho, must reconsider loop body, comment says.. what's so 'oho' about it?
1161 pc-=s.m_Operand+1;
1162 here=pc;
1163 }
1164 break;
1165 case CSop::opQuest0:
1166 // two branches, both forward..
1167 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1168 m_Strip[here+s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1169 break;
1170 case CSop::opQuest1:
1171 // just an empty.. aren't we tired of justanempties?
1172 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1173 break;
1174 case CSop::opLeftParen: // they say it's not significan there..
1175 case CSop::opRightParen:
1176 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1177 break;
1178 case CSop::opChoice0:// mark the first two branches..
1179 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1180 ASSERT(m_Strip[pc+s.m_Operand].m_Operator==CSop::opOr1);
1181 m_Strip[here+s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1182 break;
1183 case CSop::opOr0:// done a branch, find the end of choice..
1184 if(m_Strip[here].m_MatchData&maskAfter){
1185 for(look=1;(s=m_Strip[pc+look]).m_Operator!=CSop::opChoice1;look+=s.m_Operand)
1186 ASSERT(s.m_Operator==CSop::opOr1);
1187 m_Strip[here+look].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1188 }
1189 break;
1190 case CSop::opOr1: // Propagate Choice's marking..
1191 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1192 if(m_Strip[pc+s.m_Operand].m_Operator!=CSop::opChoice1){
1193 ASSERT(m_Strip[pc+s.m_Operand].m_Operator==CSop::opOr1);
1194 m_Strip[here+s.m_Operand].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1195 }
1196 break;
1197 case CSop::opChoice1: // Just empty.. :-)..
1198 m_Strip[here+1].m_MatchData|=(m_Strip[here].m_MatchData&maskAfter)?maskAfter:0;
1199 break;
1200#ifdef _DEBUG
1201 default:
1202 ASSERT(FALSE);
1203 break;
1204#endif
1205 }
1206 }
1207}
1208
1209void CRegEx::MatchStatesCopy(BYTE dst,BYTE src)
1210{
1211int stripLen = m_Strip.GetSize();
1212 for(int tmp=0;tmp<stripLen;tmp++){
1213 // I believe this can be optimized, easily..
1214 m_Strip[tmp].m_MatchData&=~dst;
1215 m_Strip[tmp].m_MatchData|=(m_Strip[tmp].m_MatchData&src)?dst:0;
1216 }
1217}
1218
1219BOOL CRegEx::MatchStatesEqual(BYTE m1,BYTE m2)
1220{
1221int stripLen = m_Strip.GetSize();
1222 for(int tmp=0;tmp<stripLen;tmp++){
1223 BYTE mm = m_Strip[tmp].m_MatchData;
1224 if(((mm&m1) && (mm&m2)) || !(mm&(m1|m2)))
1225 continue;
1226 return FALSE;
1227 }
1228 return TRUE;
1229}
1230
1231LPCTSTR CRegEx::MatchSlow(LPCTSTR begin,LPCTSTR end,int from,int to)
1232{
1233 MatchStatesClear(CSop::stCurrent);
1234 m_Strip[from].m_MatchData|=CSop::stCurrent;
1235 MatchStep(from,to,CSop::stCurrent,charNothing,CSop::stCurrent);
1236LPCTSTR mp = NULL;
1237int c = (m_mBegin==m_mPointer)?charOut:(int)(BYTE)begin[-1];
1238LPCTSTR p = begin;
1239 for(;;){
1240 // next character..
1241 int lastc = c;
1242 c = (p==m_mEnd)?charOut:(int)*(BYTE*)p;
1243 // Now we start to wonder if there is an EOL and/or BOL between lastc and c
1244 int flagc = 0;
1245 int i = 0;
1246 if((lastc=='\n' && m_Flags&regNewLine) || (lastc==charOut && !(m_mFlags&regNotBOL))){
1247 flagc = charBOL;
1248 i = m_BOLs;
1249 }
1250 if((c=='\n' && m_Flags&regNewLine) || (c==charOut && !(m_mFlags&regNotEOL))){
1251 flagc = (flagc==charBOL)?charBOLEOL:charEOL;
1252 i+=m_EOLs;
1253 }
1254 if(i){
1255 for(;i>0;i--)
1256 MatchStep(from,to,CSop::stCurrent,flagc,CSop::stCurrent);
1257 }
1258 // Now we wonder about word boundaries..
1259 if((flagc==charBOL || (lastc!=charOut && !isWordableChar(lastc))) && (c!=charOut && isWordableChar(c)))
1260 flagc=charBOW;
1261 if((lastc!=charOut && isWordableChar(lastc)) && (flagc==charEOL || (c!=charOut && !isWordableChar(c))))
1262 flagc=charEOW;
1263 if(flagc==charBOW || flagc==charEOW){
1264 MatchStep(from,to,CSop::stCurrent,flagc,CSop::stCurrent);
1265 }
1266 // Are we done we all wonder??
1267 if(m_Strip[to].m_MatchData&CSop::stCurrent)
1268 mp=p;
1269 if(MatchStatesEqual(CSop::stCurrent,CSop::stEmpty) || p==end)
1270 break;// Again, we're obliged to note break out. We do.
1271 // Sucks.. we have to face this character..
1272 MatchStatesCopy(CSop::stTemp,CSop::stCurrent);
1273 MatchStatesCopy(CSop::stCurrent,CSop::stEmpty);
1274 ASSERT(c!=charOut);
1275 MatchStep(from,to,CSop::stTemp,c,CSop::stCurrent);
1276 MatchStep(from,to,CSop::stCurrent,charNothing,CSop::stCurrent);
1277 p++;
1278 }
1279 return mp;
1280}
1281
1282LPCTSTR CRegEx::MatchDissect(LPCTSTR begin,LPCTSTR end,int from,int to)
1283{
1284LPCTSTR sp = begin, dp;
1285LPCTSTR stp, rest, tail, ssp, oldssp, sep;
1286int ssub, esub;
1287int es;
1288int i;
1289 for(int ss=from;ss<to;ss = es){
1290 // Identify end of SubRE
1291 es = ss;
1292 switch(m_Strip[es].m_Operator){
1293 case CSop::opPlus0:
1294 case CSop::opQuest0:
1295 es+=m_Strip[es].m_Operand;
1296 break;
1297 case CSop::opChoice0:
1298 while(m_Strip[es].m_Operator!=CSop::opChoice1)
1299 es+=m_Strip[es].m_Operand;
1300 break;
1301 }
1302 es++;
1303 // Figure out what it matched
1304 switch(m_Strip[ss].m_Operator){
1305 case CSop::opEnd:
1306 ASSERT(FALSE);
1307 break;
1308 case CSop::opChar:
1309 sp++;
1310 break;
1311 case CSop::opBOL:
1312 case CSop::opEOL:
1313 case CSop::opBOW:
1314 case CSop::opEOW:
1315 break;
1316 case CSop::opAny:
1317 case CSop::opAnyOf:
1318 sp++;
1319 break;
1320 case CSop::opBackRef0:
1321 case CSop::opBackRef1:
1322 ASSERT(FALSE);
1323 break;
1324 // Cases where lenght of match is hard to find..
1325 case CSop::opQuest0:
1326 stp=end;
1327 for(;;){
1328 // How long could this one be??
1329 rest = MatchSlow(sp,stp,ss,es);
1330 ASSERT(rest);// It did match.. It should've..
1331 // Could the rest match the rest? (good question)
1332 tail = MatchSlow(rest,end,es,to);
1333 if(tail==end)
1334 break;// yup.
1335 // nope, try a shorter match for this one..
1336 stp=rest-1;
1337 ASSERT(stp>=sp);// It did work.. It should've..
1338 }
1339 ssub=ss+1;
1340 esub=es-1;
1341 // Did innards match?
1342 if(MatchSlow(sp,rest,ssub,esub)){
1343 dp = MatchDissect(sp,rest,ssub,esub);
1344 ASSERT(dp==rest);
1345 }else// nope..
1346 ASSERT(sp==rest);
1347 sp = rest;
1348 break;
1349 case CSop::opPlus0:
1350 stp=end;
1351 for(;;){
1352 // How long could this one be??
1353 rest = MatchSlow(sp,stp,ss,es);
1354 ASSERT(rest);// It did.. It should've..
1355 // Could the rest match the rest?
1356 tail = MatchSlow(rest,end,es,to);
1357 if(tail==end)
1358 break;// yup.
1359 // nope..
1360 stp=rest-1;
1361 ASSERT(stp>=sp);// It should've worked, we believe..
1362 }
1363 ssub=ss+1;
1364 esub=es-1;
1365 ssp=sp;
1366 oldssp=ssp;
1367 for(;;){// Find last match of innards..
1368 sep = MatchSlow(ssp,rest,ssub,esub);
1369 if((!sep) || sep==ssp)
1370 break; // Failed or matched nothin'
1371 oldssp=ssp;
1372 ssp=sep;
1373 }
1374 if(!sep){
1375 // Last successfull..
1376 sep=ssp;
1377 ssp=oldssp;
1378 }
1379 ASSERT(sep=rest);// Must exhaust substring they say..
1380 VERIFY(MatchSlow(ssp,sep,ssub,esub)==rest);// Assert or verify - that is the question..
1381 dp = MatchDissect(ssp,sep,ssub,esub);
1382 ASSERT(dp==sep);
1383 sp=rest;
1384 break;
1385 case CSop::opChoice0:
1386 stp = end;
1387 for(;;){
1388 // how long..
1389 rest = MatchSlow(sp,stp,ss,es);
1390 ASSERT(rest);
1391 // Could it..
1392 tail = MatchSlow(rest,end,es,to);
1393 if(tail==end)
1394 break;// y
1395 // n
1396 stp = rest-1;
1397 ASSERT(stp>=sp);
1398 }
1399 ssub=ss+1;
1400 esub=ss+m_Strip[ss].m_Operand-1;
1401 ASSERT(m_Strip[esub].m_Operator==CSop::opOr0);
1402 for(;;){// Find first matching branch..
1403 if(MatchSlow(sp,rest,ssub,esub)==rest)
1404 break;
1405 // this one missed, try next..
1406 ASSERT(m_Strip[esub].m_Operator==CSop::opOr0);
1407 esub++;
1408 ASSERT(m_Strip[esub].m_Operator==CSop::opOr1);
1409 ssub=esub+1;
1410 esub+=m_Strip[esub].m_Operand;
1411 if(m_Strip[esub].m_Operator==CSop::opOr1)
1412 esub--;
1413 else
1414 ASSERT(m_Strip[esub].m_Operator==CSop::opChoice1);
1415 }
1416 dp = MatchDissect(sp,rest,ssub,esub);
1417 ASSERT(dp==rest);
1418 sp=rest;
1419 break;
1420 case CSop::opPlus1:
1421 case CSop::opQuest1:
1422 case CSop::opOr0:
1423 case CSop::opOr1:
1424 case CSop::opChoice1:
1425 ASSERT(FALSE);
1426 break;
1427 case CSop::opLeftParen:
1428 i = m_Strip[ss].m_Operand;
1429 ASSERT(0<i && i<=m_Subexps);
1430 m_Matches[i].m_Begin=sp-m_mBegin;
1431 break;
1432 case CSop::opRightParen:
1433 i = m_Strip[ss].m_Operand;
1434 ASSERT(0<i && i<=m_Subexps);
1435 m_Matches[i].m_End=sp-m_mBegin;
1436 break;
1437#ifdef _DEBUG
1438 default:// Uh.. oh..
1439 ASSERT(FALSE);
1440 break;
1441#endif
1442 }
1443 }
1444 ASSERT(sp==end);
1445 return sp;
1446}
1447
1448LPCTSTR CRegEx::MatchBackRef(LPCTSTR begin,LPCTSTR end,int from,int to,int level)
1449{
1450LPCTSTR sp = begin;
1451BOOL hard = FALSE;
1452 // Get as far as we can as long as it's easy
1453 for(int ss=from;!hard && ss<to;ss++){
1454 CSop s = m_Strip[ss];
1455 switch(s.m_Operator){
1456 case CSop::opChar:
1457 if(sp==end || *sp++ != s.m_Operand)
1458 return NULL;
1459 break;
1460 case CSop::opAny:
1461 if(sp==end)
1462 return NULL;
1463 sp++;// I'm sure this ++ could be embedded in previous expression..
1464 break;
1465 case CSop::opAnyOf:
1466 if(sp==end || !m_Sets[s.m_Operand].IsIn(*sp++))
1467 return NULL;
1468 break;
1469 case CSop::opBOL:
1470 if(!((sp==m_mBegin && !(m_mFlags&regNotBOL)) || (sp<m_mEnd && *(sp-1)=='\n' && (m_Flags&regNewLine))))
1471 return NULL;
1472 break;
1473 case CSop::opEOL:
1474 if(!((sp==m_mEnd && !(m_mFlags&regNotEOL)) || (sp<m_mEnd && *sp=='\n' && (m_Flags&regNewLine))))
1475 return NULL;
1476 break;
1477 case CSop::opBOW:
1478 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))))
1479 return NULL;
1480 break;
1481 case CSop::opEOW:
1482 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)))))
1483 return NULL;
1484 break;
1485 case CSop::opQuest1:
1486 break;
1487 case CSop::opOr0:// Matches null, but needs to skip
1488 ss++;
1489 s = m_Strip[ss];
1490 do{
1491 ASSERT(s.m_Operator==CSop::opOr1);
1492 ss+=s.m_Operand;
1493 }while((s=m_Strip[ss]).m_Operator!=CSop::opChoice1);
1494 // Now we should note that ss++ gets us past the Choice1..
1495 break;
1496 default:
1497 // Have to make a choice..
1498 hard=TRUE;
1499 break;
1500 }
1501 }
1502 if(!hard){// That was it..
1503 if(sp!=end)
1504 return NULL;
1505 return sp;
1506 }
1507 ss--;// Adjust for ther for's final increment..
1508 // Hard stuff.. is going on and on..
1509CSop s = m_Strip[ss];
1510int i, len, offsave;
1511int ssub,esub;
1512LPCTSTR ssp, dp;
1513 switch(s.m_Operator){
1514 case CSop::opBackRef0:// The vilest depths they say.. If I only knew what the 'viles' stands for..
1515 i = s.m_Operand;
1516 ASSERT(0<i && i<=m_Subexps);
1517 if(m_Matches[i].m_End<0)
1518 return NULL;
1519 ASSERT(m_Matches[i].m_Begin>=0);
1520 len = m_Matches[i].GetLength();
1521 ASSERT((end-m_mBegin)>=len);
1522 if(sp>end-len)
1523 return NULL;// Not enough left to match..
1524 ssp = m_mBegin+m_Matches[i].m_Begin;
1525 if(memcmp(sp,ssp,len))
1526 return NULL;
1527 while(m_Strip[ss]!=CSop(CSop::opBackRef1,i))
1528 ss++;
1529 return MatchBackRef(sp+len,end,ss+1,to,level-1);
1530 break;
1531 case CSop::opQuest0:// to null or not they wonder..
1532 dp = MatchBackRef(sp,end,ss+1,to,level);
1533 if(dp)
1534 return dp;// not..
1535 return MatchBackRef(sp,end,ss+s.m_Operand+1,to,level-1);
1536 break;
1537 case CSop::opPlus0:
1538 ASSERT(m_mLastPos.GetSize());
1539 ASSERT(level+1 <= m_Pluses);
1540 m_mLastPos[level+1]=sp;
1541 return MatchBackRef(sp,end,ss+1,to,level+1);
1542 break;
1543 case CSop::opPlus1:
1544 if(sp == m_mLastPos[level])// Last pass matched null
1545 return MatchBackRef(sp,end,ss+1,to,level-1);
1546 // Try another pass..
1547 m_mLastPos[level]=sp;
1548 dp = MatchBackRef(sp,end,ss-s.m_Operand+1,to,level);
1549 if(dp)
1550 return dp;
1551 return MatchBackRef(sp,end,ss+1,to,level-1);
1552 break;
1553 case CSop::opChoice0:// find the right one, ifany
1554 ssub = ss+1;
1555 esub = ss+s.m_Operand-1;
1556 ASSERT(m_Strip[esub].m_Operator==CSop::opOr0);
1557 for(;;){// Find first matching branch.
1558 dp = MatchBackRef(sp,end,ssub,esub,level);
1559 if(dp)
1560 return dp;
1561 // This one missed, try next one..
1562 if(m_Strip[esub].m_Operator==CSop::opChoice1)
1563 return NULL;// There is none..
1564 esub++;
1565 ASSERT(m_Strip[esub].m_Operator==CSop::opOr1);
1566 ssub=esub+1;
1567 esub+=m_Strip[esub].m_Operand;
1568 if(m_Strip[esub].m_Operator==CSop::opOr1)
1569 esub--;
1570 else
1571 ASSERT(m_Strip[esub].m_Operator==CSop::opChoice1);
1572 }
1573 break;
1574 case CSop::opLeftParen:// Must undo assignment if rest fails..
1575 i = s.m_Operand;
1576 ASSERT(0<i && i<=m_Subexps);
1577 offsave = m_Matches[i].m_Begin;
1578 m_Matches[i].m_Begin = sp-m_mBegin;
1579 dp = MatchBackRef(sp,end,ss+1,to,level);
1580 if(dp)
1581 return dp;
1582 m_Matches[i].m_Begin=offsave;
1583 return NULL;
1584 break;
1585 case CSop::opRightParen: // Must undo assignment if rest fails..
1586 i = s.m_Operand;
1587 ASSERT(0<i && i<=m_Subexps);
1588 offsave = m_Matches[i].m_End;
1589 m_Matches[i].m_End = sp-m_mBegin;
1590 dp = MatchBackRef(sp,end,ss+1,to,level);
1591 if(dp)
1592 return dp;
1593 m_Matches[i].m_End = offsave;
1594 return NULL;
1595 break;
1596 #ifdef_DEBUG
1597 default:
1598 ASSERT(FALSE);
1599 break;
1600#endif
1601 }
1602 ASSERT(FALSE);
1603 return NULL;// Anyway - we can never get here..
1604}
1605
1606 #ifdef_DEBUG
1607void CRegEx::CSop::Dump(CDumpContext& dc)
1608{
1609 switch(m_Operator){
1610 case opEnd:
1611 dc << "end";
1612 break;
1613 case opChar:
1614 dc << "char('" << (char)m_Operand << "')";
1615 break;
1616 case opBOL:
1617 dc << "BOL";
1618 break;
1619 case opEOL:
1620 dc << "EOL";
1621 break;
1622 case opAny:
1623 dc << "any";
1624 break;
1625 case opAnyOf:
1626 dc << "anyOf(" << m_Operand << ")";
1627 break;
1628 case opBackRef0:
1629 dc << "[ backref(" << m_Operand << ")";
1630 break;
1631 case opBackRef1:
1632 dc << "] backref(" << m_Operand << ")";
1633 break;
1634 case opPlus0:
1635 dc << "[ + (" << m_Operand << ")";
1636 break;
1637 case opPlus1:
1638 dc << "] + (" << m_Operand << ")";
1639 break;
1640 case opQuest0:
1641 dc << "[ ? (" << m_Operand << ")";
1642 break;
1643 case opQuest1:
1644 dc << "] ? (" << m_Operand << ")";
1645 break;
1646 case opLeftParen:
1647 dc << "[ ( (" << m_Operand << ")";
1648 break;
1649 case opRightParen:
1650 dc << "] ) (" << m_Operand << ")";
1651 break;
1652 case opChoice0:
1653 dc << "[ choice (" << m_Operand << ")";
1654 break;
1655 case opOr0:
1656 dc << "[ | (" << m_Operand << ")";
1657 break;
1658 case opOr1:
1659 dc << "] | (" << m_Operand << ")";
1660 break;
1661 case opChoice1:
1662 dc << "] choice (" << m_Operand << ")";
1663 break;
1664 case opBOW:
1665 dc << "BOW";
1666 break;
1667 case opEOW:
1668 dc << "EOW";
1669 break;
1670 }
1671}
1672void CRegEx::DumpStrip(CDumpContext& dc)
1673{
1674 for(int tmp=0;tmp<m_Strip.GetSize();tmp++)
1675 dc << tmp << ": " << m_Strip[tmp] << ";\n";
1676}
1677#endif
1678
1679
1680CString CRegEx::GetMatch(int match)
1681{
1682CString rv;
1683 if(!m_Matches.GetSize())
1684 return rv;
1685 ASSERT(m_Matches[0].m_Begin<m_Input.GetLength() && m_Matches[0].m_End<=m_Input.GetLength());
1686 if(match==matchPreMatch)
1687 return m_Input.Left(m_Matches[0].m_Begin);
1688 if(match==matchPostMatch)
1689 return m_Input.Mid(m_Matches[0].m_End);
1690 if(match<0 || match >= m_Matches.GetSize())
1691 return rv;
1692 if(m_Matches[match].m_Begin<0 || m_Matches[match].m_End<0)
1693 return rv;
1694 ASSERT(m_Matches[match].m_Begin<m_Input.GetLength() && m_Matches[match].m_End<=m_Input.GetLength());
1695 rv = m_Input.Mid(m_Matches[match].m_Begin,m_Matches[match].m_End-m_Matches[match].m_Begin);
1696 return rv;
1697}
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 @@
1#ifndef __REGEX_H
2#define __REGEX_H
3
4 class CRegEx{
5public:
6 CString GetMatch(int match=0);
7 CString m_Input;
8 struct CMatch{
9 CMatch() : m_Begin(-1), m_End(-1) {}
10 int GetLength() { return m_End-m_Begin; }
11 int m_Begin;
12 int m_End;
13 };
14 typedefCArray<CMatch,CMatch&> CMatchBox;
15 enum{
16 matchMatch = 0,
17 matchPreMatch = -1,
18 matchPostMatch = -2
19 };
20 CMatchBox m_Matches;
21 enum{
22 charOut = 256,
23 charBOL, charEOL, charBOLEOL, charNothing, charBOW, charEOW,
24 charMaxCode = charEOW,
25 charNNChars = (charMaxCode-255)
26 };
27 int m_mFlags;
28 enum{
29 regeSuccess = 0,
30 regeNoMatch = 1, regeBadPattern, regeCollate, regeCType, regeEscape, regeSubReg, regeBracket,
31 regeParen, regeBrace, regeBadBrace, regeRange, regeSpace, regeBadRepeat, regeEmpty, regeAssert,
32 regeInvArg
33 };
34 int m_Error;
35 CRegEx();
36 BOOL m_bCompiled;
37 CString m_Pattern;
38 BOOL m_bBackRefs;
39 int m_Pluses;
40 CString m_Must;
41 BYTE m_Category[CHAR_MAX-CHAR_MIN+1];
42 int m_Categories;
43 int m_EOLs;
44 int m_BOLs;
45 int m_iFlags;
46 int m_Subexps;
47 struct CSop {
48 void Dump(CDumpContext& dc);
49 CSop(){}
50 CSop(BYTE op,DWORD opnd=0) : m_Operator(op), m_Operand(opnd) {}
51 BOOL operator==(CSop& other) {return m_Operator==other.m_Operator && m_Operand==other.m_Operand;}
52 BOOL operator!=(CSop& other) { return !((*this)==other);}
53 enum{
54 opEnd = 1, opChar, opBOL, opEOL, opAny, opAnyOf, opBackRef0, opBackRef1,
55 opPlus0, opPlus1, opQuest0, opQuest1, opLeftParen, opRightParen, opChoice0,
56 opOr0, opOr1, opChoice1, opBOW, opEOW
57 };
58 BYTE m_Operator;
59 DWORD m_Operand;
60 enum{
61 stCurrent = 1, stFresh = 2, stTemp = 4, stEmpty = 8
62 };
63 BYTE m_MatchData;
64 };
65 typedef CArray<CSop,CSop&> CStrip;
66 CStrip m_Strip;
67 int m_Flags;
68 struct CSet{
69 CSet() : m_Hash(0) { memset(m_Set,0,sizeof(m_Set)); }
70 CSet(CSet& src) { (*this)=src; }
71 CSet& operator=(CSet& src) { memmove(this,&src,sizeof(*this)); return *this; }
72 BOOL operator==(CSet& other) { if(m_Hash!=other.m_Hash)return FALSE;return !memcmp(m_Set,other.m_Set,sizeof(m_Set)); }
73 enum{
74 size = (CHAR_MAX-CHAR_MIN+1)
75 };
76 BOOL m_Set[size];
77 BYTE m_Hash;
78 public:
79 UCHAR GetOnly();
80 void Sub(UCHAR c);
81 BOOL IsIn(UCHAR c);
82 void Add(UCHAR c);
83 };
84 typedef CArray<CSet,CSet&> CSets;
85 CSets m_Sets;
86 enum{
87 // Compile flags
88 regBasic = 0, regExtended = 1,
89 regIgnoreCase = 2,
90 regNoSubExpressions = 4,// Also works for matching.
91 regNewLine = 16,
92 regLiteral = 32,
93 // Match Flags
94 regNotBOL = 1,
95 regNotEOL = 2,
96 regOneMatch=64,
97 regBackRefs=128,
98 // iFlags
99 iflagsUseBOL=1, iflagsUseEOL=2, iflagsBad=4
100 };
101 CString Replace(LPCTSTR src,LPCTSTR rep,int flags=0);
102 BOOL Match(LPCTSTR src,int flags=0);
103 BOOL Compile(LPCTSTR regex,int flags=0);
104private:
105 #ifdef_DEBUG
106 void DumpStrip(CDumpContext& dc);
107#endif
108 LPCTSTR MatchBackRef(LPCTSTR begin,LPCTSTR end,int from,int to,int level);
109 typedef CArray<LPCTSTR,LPCTSTR> CStrPtrArray;
110 CStrPtrArray m_mLastPos;
111 LPCTSTR MatchDissect(LPCTSTR begin,LPCTSTR end,int from,int to);
112 LPCTSTR MatchSlow(LPCTSTR begin,LPCTSTR end,int from,int to);
113 LPCTSTR m_cOldP;
114 BOOL MatchStatesEqual(BYTE m1,BYTE m2);
115 LPCTSTR m_mBegin;
116 void MatchStatesCopy(BYTE dst,BYTE src);
117 void MatchStep(int from,int to,BYTE maskBefore,int charCode,BYTE maskAfter);
118 void MatchStatesClear(BYTE mask);
119 LPCTSTR MatchFast(LPCTSTR begin);
120 LPCTSTR m_mEnd;
121 LPCTSTR m_mPointer;
122 BOOL ParseBREexp(BOOL ordinaryStar);
123 void ParseBRE(int stopa=0,int stopb=0);
124 void ParseLiteral();
125 int CountPluses();
126 void FigureMust();
127 BOOL IsInSameSets(UCHAR c1,UCHAR c2);
128 BOOL IsInSets(UCHAR c);
129 void Categorize();
130 int StripDuplicate(int from,int to);
131 void EmitRepeat(int pos,int from,int to);
132 UCHAR ParseBracketSymbol();
133 UCHAR ParseBracketCollatingElement(UCHAR term);
134 void ParseBracketEClass(CSet& cset);
135 void ParseBracketCClass(CSet& cset);
136 void ParseBracketTerm(CSet& cset);
137 int StoreSet(CSet& cset);
138 void ParseBracket();
139 int ParseCount();
140 void EmitNonNewLineAny();
141 void EmitOrdinary(UCHAR c);
142 void StripInsert(int pos,CSop& sop);
143 void ParseEREexp();
144 void ParseERE(int stop=0);
145 struct CParenthesis{
146 long m_Begin;
147 long m_End;
148 CParenthesis(long b=0,long e=0) : m_Begin(b), m_End(e) {}
149 };
150 typedef CArray<CParenthesis,CParenthesis&> CParens;
151 CParens m_ParseParens;
152 int m_ParsePointer;
153};
154 #ifdef_DEBUG
155inline CDumpContext& operator<<(CDumpContext& dc, CRegEx::CSop& sop) { sop.Dump(dc); return dc; }
156#endif
157
158#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 @@
1 #ifndef__SNMPEXTDLL_H
2#define __SNMPEXTDLL_H
3
4#include "snmpeer.h"
5
6#include <snmp.h>
7
8namespace Klever {
9
10 class CSNMPExtDLL : public CSNMPeer{
11public:
12 HINSTANCE m_hInstance;
13 HANDLE m_hEvent;
14 AsnObjectIdentifier m_OID;
15 BOOL (SNMP_FUNC_TYPE *m_extInit)(DWORD dw,HANDLE h,AsnObjectIdentifier* aoid);
16 BOOL (SNMP_FUNC_TYPE *m_extQuery)(BYTE b,RFC1157VarBindList* rvbl,AsnInteger* ai1,AsnInteger* ai2);
17 BOOL (SNMP_FUNC_TYPE *m_extTrap)(AsnObjectIdentifier*,AsnNetworkAddress*,AsnInteger*,AsnInteger*,AsnTimeticks*,RFC1157VarBindList*);
18
19 HINSTANCE m_hSNMPAPI;
20 void (SNMP_FUNC_TYPE *m_snmpOIDFree)(AsnObjectIdentifier*);
21 LPVOID (SNMP_FUNC_TYPE *m_snmpAlloc)(UINT);
22 void (SNMP_FUNC_TYPE *m_snmpFree)(LPVOID);
23 void (SNMP_FUNC_TYPE *m_snmpVBLFree)(RFC1157VarBindList* vbl);
24 void InitSNMP() {
25 m_hSNMPAPI = ::LoadLibraryEx("SNMPAPI",NULL,0);
26 if(!m_hSNMPAPI)
27 return;
28 *(FARPROC*)&m_snmpOIDFree = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilOidFree");
29 *(FARPROC*)&m_snmpAlloc = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilMemAlloc");
30 *(FARPROC*)&m_snmpFree = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilMemFree");
31 *(FARPROC*)&m_snmpVBLFree = ::GetProcAddress(m_hSNMPAPI,"SnmpUtilVarBindListFree");
32 if(
33 (m_snmpFree && !m_snmpAlloc) ||
34 (m_snmpAlloc && !m_snmpFree)
35 )
36 DeinitSNMP();
37 }
38 void DeinitSNMP() {
39 if(!m_hSNMPAPI)
40 return;
41 ::FreeLibrary(m_hSNMPAPI);
42 m_hSNMPAPI=NULL;
43 }
44 void SNMPFreeOID(AsnObjectIdentifier* oid) {
45 if(m_hSNMPAPI && m_snmpOIDFree)
46 (*m_snmpOIDFree)(oid);
47 else
48 ::GlobalFree((HGLOBAL)oid->ids);
49 }
50 LPVOID SNMPAlloc(UINT size) {
51 if(m_hSNMPAPI && m_snmpAlloc)
52 return (*m_snmpAlloc)(size);
53 else
54 return ::GlobalAlloc(GMEM_FIXED,size);
55 }
56 void SNMPFree(LPVOID addr) {
57 if(m_hSNMPAPI && m_snmpFree)
58 (*m_snmpFree)(addr);
59 else
60 :: GlobalFree((HGLOBAL)addr);
61 }
62 void SNMPFreeVBL(RFC1157VarBindList& vbl) {
63 if(m_hSNMPAPI && m_snmpVBLFree)
64 (*m_snmpVBLFree)(&vbl);
65 else{
66 for(UINT tmp=0;tmp<vbl.len;tmp++) {
67 SNMPFree(vbl.list[tmp].name.ids);
68 switch(vbl.list[tmp].value.asnType){
69 case ASN_OCTETSTRING:
70 case ASN_SEQUENCE:
71 case ASN_RFC1155_IPADDRESS:
72 case ASN_RFC1155_OPAQUE:
73 // case ASN_RFC1213_DISPSTRING:
74 if(vbl.list[tmp].value.asnValue.arbitrary.dynamic)
75 SNMPFree(vbl.list[tmp].value.asnValue.arbitrary.stream);
76 break;
77 case ASN_OBJECTIDENTIFIER:
78 SNMPFree(vbl.list[tmp].value.asnValue.object.ids);
79 break;
80 default:
81 break;
82 }
83 }
84 SNMPFree(vbl.list);
85 }
86 }
87
88 BOOL SNMPBuildVBL(RFC1157VarBindList& vbl,CSNMPVarBindList& in) {
89 vbl.len = in.GetCount();
90 vbl.list = (RFC1157VarBind*)SNMPAlloc(sizeof(RFC1157VarBind)*vbl.len);
91 POSITION p = in.GetHeadPosition();
92 UINT ptr = 0;
93 while(p){
94 CSNMPVarBind& vb = in.GetNext(p);
95 ASSERT(ptr<vbl.len);
96 SNMPBuildVB(vbl.list[ptr++],vb);
97 }
98 return TRUE;
99 }
100 BOOL SNMPBuildVB(RFC1157VarBind& vb,CSNMPVarBind& in) {
101 ASSERT(in.name.type==CASNAny::typeASNOID);
102 return SNMPBuildOID(vb.name,in.name.value.oid) && SNMPBuildAA(vb.value,in.value);
103 }
104 BOOL SNMPBuildAA(AsnAny& aa,CASNAny& in) {
105 aa.asnType=in.type;
106 switch(in.type) {
107 case CASNAny::typeASNInteger:
108 aa.asnValue.number=in.value.number; break;
109 case CASNAny::typeASNOctetString:
110 // case CASNAny::typeASNDispString:
111 SNMPBuildOS(aa.asnValue.string,in.value.string); break;
112 case CASNAny::typeASNNull:
113 break;
114 case CASNAny::typeASNOID:
115 SNMPBuildOID(aa.asnValue.object,in.value.oid); break;
116 case CASNAny::typeASNSequence:
117 // case CASNAny::typeASNSequenceOf:
118 SNMPBuildOS(aa.asnValue.sequence,in.value.sequence); break;
119 case CASNAny::typeASNIP:
120 SNMPBuildFLOS(aa.asnValue.address,(LPBYTE)&in.value.ip,sizeof(in.value.ip)); break;
121 case CASNAny::typeASNCounter:
122 aa.asnValue.counter = in.value.counter; break;
123 case CASNAny::typeASNGauge:
124 aa.asnValue.gauge = in.value.gauge; break;
125 case CASNAny::typeASNTicks:
126 aa.asnValue.ticks = in.value.ticks; break;
127 case CASNAny::typeASNOpaque:
128 ASSERT(in.storeType==CASNAny::storeDynamic);
129 SNMPBuildOS(aa.asnValue.arbitrary,in.value.data); break;
130 break;
131 default:
132 ASSERT(FALSE);
133 return FALSE;
134 }
135 return TRUE;
136 }
137 BOOL SNMPBuildOS(AsnOctetString& os,CASNAny::asnOctetString& in) {
138 return SNMPBuildFLOS(os,in.data,in.size);
139 }
140 BOOL SNMPBuildOID(AsnObjectIdentifier& oid,CASNAny::asnOID& in) {
141 oid.idLength = in.size/sizeof(UINT);
142 ASSERT(!(in.size%sizeof(UINT)));
143 VERIFY(oid.ids = (UINT*)SNMPAlloc(in.size));
144 memmove(oid.ids,in.data,in.size);
145 return TRUE;
146 }
147 BOOL SNMPBuildFLOS(AsnOctetString& os,LPBYTE data,UINT size) {
148 os.length = size;
149 VERIFY(os.stream = (BYTE*)SNMPAlloc(os.length));
150 os.dynamic=TRUE;
151 memmove(os.stream,data,size);
152 return TRUE;
153 }
154 BOOL SNMPParseVBL(RFC1157VarBindList& vbl,CSNMPVarBindList& ou) {
155 for(UINT tmp=0;tmp<vbl.len;tmp++){
156 CSNMPVarBind vb;
157 SNMPParseVB(vbl.list[tmp],vb);
158 ou.AddTail(vb);
159 }
160 return TRUE;
161 }
162 BOOL SNMPParseVB(RFC1157VarBind& vb,CSNMPVarBind& ou) {
163 ou.name.Set(CASNAny::typeASNOID,(LPBYTE)vb.name.ids,vb.name.idLength*sizeof(UINT));
164 return SNMPParseAA(vb.value,ou.value);
165 }
166 BOOL SNMPParseAA(AsnAny& aa,CASNAny& ou) {
167 switch(aa.asnType){
168 case ASN_INTEGER:
169 ou.Set(CASNAny::typeASNInteger,aa.asnValue.number); break;
170 case ASN_OCTETSTRING:
171 // case ASN_RFC1213_DISPSTRING:
172 ou.Set(CASNAny::typeASNOctetString,aa.asnValue.string.stream,aa.asnValue.string.length); break;
173 case ASN_OBJECTIDENTIFIER:
174 ou.Set(CASNAny::typeASNOID,(LPBYTE)aa.asnValue.object.ids,aa.asnValue.object.idLength);
175 SNMPParseOID(aa.asnValue.object,ou.value.oid); break;
176 case ASN_SEQUENCE:
177 ou.Set(CASNAny::typeASNSequence,aa.asnValue.sequence.stream,aa.asnValue.sequence.length); break;
178 case ASN_RFC1155_IPADDRESS:
179 SNMPParseIP(aa.asnValue.address,ou); break;
180 case ASN_RFC1155_COUNTER:
181 ou.Set(CASNAny::typeASNCounter,(LONG)aa.asnValue.counter); break;
182 case ASN_RFC1155_GAUGE:
183 ou.Set(CASNAny::typeASNGauge,(LONG)aa.asnValue.gauge); break;
184 case ASN_RFC1155_TIMETICKS:
185 ou.Set(CASNAny::typeASNTicks,(LONG)aa.asnValue.ticks); break;
186 case ASN_RFC1155_OPAQUE:
187 ou.Set(CASNAny::typeASNOpaque,aa.asnValue.arbitrary.stream,aa.asnValue.arbitrary.length); break;
188 case ASN_NULL:
189 ou.Free(); break;
190 default:
191 ASSERT(FALSE);
192 return FALSE;
193 }
194 return TRUE;
195 }
196 BOOL SNMPParseOID(AsnObjectIdentifier& oid,CASNAny::asnOID& ou) {
197 ASSERT(ou.size==(oid.idLength*sizeof(UINT)));
198 memmove(ou.data,oid.ids,ou.size);
199 return TRUE;
200 }
201 BOOL SNMPParseIP(AsnIPAddress& ip,CASNAny& ou) {
202 in_addr i;
203 if(ip.length>sizeof(i))
204 return FALSE;
205 i.s_addr=0;
206 memmove(&i,ip.stream,ip.length);
207 ou.Set(i);
208 return TRUE;
209 }
210
211
212 CSNMPExtDLL(LPCTSTR dllName) : m_hInstance(NULL) { InitSNMP(); Init(dllName); }
213 ~CSNMPExtDLL() { Deinit(); DeinitSNMP(); }
214
215 BOOL Init(LPCTSTR dllName) {
216 Deinit();
217 m_hInstance = ::LoadLibraryEx(dllName,NULL,0);
218 if(!m_hInstance)
219 return FALSE;
220 *(FARPROC*)&m_extInit = ::GetProcAddress(m_hInstance,"SnmpExtensionInit");
221 *(FARPROC*)&m_extQuery = ::GetProcAddress(m_hInstance,"SnmpExtensionQuery");
222 *(FARPROC*)&m_extTrap = ::GetProcAddress(m_hInstance,"SnmpExtensionTrap");
223 if(!(m_extInit && m_extQuery && m_extTrap)){
224 Deinit();
225 return FALSE;
226 }
227 if(!((*m_extInit)(GetCurrentTime(),&m_hEvent,&m_OID))){
228 Deinit();
229 return FALSE;
230 }
231 return TRUE;
232 }
233 void Deinit() {
234 if(!m_hInstance)
235 return;
236 ::FreeLibrary(m_hInstance);
237 }
238 virtual BOOL Request(BYTE type,CSNMPVarBindList& in,CSNMPVarBindList& ou) {
239 RFC1157VarBindList vbl;
240 SNMPBuildVBL(vbl,in);
241 AsnInteger errorStatus, errorIndex;
242 (*m_extQuery)(type,&vbl,&errorStatus,&errorIndex);
243 ou.RemoveAll();
244 SNMPParseVBL(vbl,ou);
245 SNMPFreeVBL(vbl);
246 return TRUE;
247 }
248};
249
250};
251
252 #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 @@
1 #ifndef__SNMPOIDS_H
2 #define__SNMPOIDS_H
3
4 #define DEFINE_OID(name,oid)static UINT name[] = oid
5
6 // MIB-II OIDs
7
8#define OIDccitt {0}
9#define OIDnull {0,0}
10#define OIDiso {1}
11#define OIDorg {1,3}
12#define OIDdod {1,3,6}
13#define OIDinternet {1,3,6,1}
14#define OIDdirectory {1,3,6,1,1}
15#define OIDmgmt {1,3,6,1,2}
16#define OIDmib_2 {1,3,6,1,2,1}
17#define OIDsystem {1,3,6,1,2,1,1}
18#define OIDsysDescr {1,3,6,1,2,1,1,1}
19#define OIDsysObjectID {1,3,6,1,2,1,1,2}
20#define OIDsysUpTime {1,3,6,1,2,1,1,3}
21#define OIDsysContact {1,3,6,1,2,1,1,4}
22#define OIDsysName {1,3,6,1,2,1,1,5}
23#define OIDsysLocation {1,3,6,1,2,1,1,6}
24#define OIDsysServices {1,3,6,1,2,1,1,7}
25#define OIDtransmission {1,3,6,1,2,1,10}
26#define OIDsnmp {1,3,6,1,2,1,11}
27#define OIDsnmpInPkts {1,3,6,1,2,1,11,1}
28#define OIDsnmpInBadValues {1,3,6,1,2,1,11,10}
29#define OIDsnmpInReadOnlys {1,3,6,1,2,1,11,11}
30#define OIDsnmpInGenErrs {1,3,6,1,2,1,11,12}
31#define OIDsnmpInTotalReqVars {1,3,6,1,2,1,11,13}
32#define OIDsnmpInTotalSetVars {1,3,6,1,2,1,11,14}
33#define OIDsnmpInGetRequests {1,3,6,1,2,1,11,15}
34#define OIDsnmpInGetNexts {1,3,6,1,2,1,11,16}
35#define OIDsnmpInSetRequests {1,3,6,1,2,1,11,17}
36#define OIDsnmpInGetResponses {1,3,6,1,2,1,11,18}
37#define OIDsnmpInTraps {1,3,6,1,2,1,11,19}
38#define OIDsnmpOutPkts {1,3,6,1,2,1,11,2}
39#define OIDsnmpOutTooBigs {1,3,6,1,2,1,11,20}
40#define OIDsnmpOutNoSuchNames {1,3,6,1,2,1,11,21}
41#define OIDsnmpOutBadValues {1,3,6,1,2,1,11,22}
42#define OIDsnmpOutGenErrs {1,3,6,1,2,1,11,24}
43#define OIDsnmpOutGetRequests {1,3,6,1,2,1,11,25}
44#define OIDsnmpOutGetNexts {1,3,6,1,2,1,11,26}
45#define OIDsnmpOutSetRequests {1,3,6,1,2,1,11,27}
46#define OIDsnmpOutGetResponses {1,3,6,1,2,1,11,28}
47#define OIDsnmpOutTraps {1,3,6,1,2,1,11,29}
48#define OIDsnmpInBadVersions {1,3,6,1,2,1,11,3}
49#define OIDsnmpEnableAuthenTraps {1,3,6,1,2,1,11,30}
50#define OIDsnmpInBadCommunityNames {1,3,6,1,2,1,11,4}
51#define OIDsnmpInBadCommunityUses {1,3,6,1,2,1,11,5}
52#define OIDsnmpInASNParseErrs {1,3,6,1,2,1,11,6}
53#define OIDsnmpInTooBigs {1,3,6,1,2,1,11,8}
54#define OIDsnmpInNoSuchNames {1,3,6,1,2,1,11,9}
55#define OIDinterfaces {1,3,6,1,2,1,2}
56#define OIDifNumber {1,3,6,1,2,1,2,1}
57#define OIDifTable {1,3,6,1,2,1,2,2}
58#define OIDifEntry {1,3,6,1,2,1,2,2,1}
59#define OIDifIndex {1,3,6,1,2,1,2,2,1,1}
60#define OIDifInOctets {1,3,6,1,2,1,2,2,1,10}
61#define OIDifInUcastPkts {1,3,6,1,2,1,2,2,1,11}
62#define OIDifInNUcastPkts {1,3,6,1,2,1,2,2,1,12}
63#define OIDifInDiscards {1,3,6,1,2,1,2,2,1,13}
64#define OIDifInErrors {1,3,6,1,2,1,2,2,1,14}
65#define OIDifInUnknownProtos {1,3,6,1,2,1,2,2,1,15}
66#define OIDifOutOctets {1,3,6,1,2,1,2,2,1,16}
67#define OIDifOutUcastPkts {1,3,6,1,2,1,2,2,1,17}
68#define OIDifOutNUcastPkts {1,3,6,1,2,1,2,2,1,18}
69#define OIDifOutDiscards {1,3,6,1,2,1,2,2,1,19}
70#define OIDifDescr {1,3,6,1,2,1,2,2,1,2}
71#define OIDifOutErrors {1,3,6,1,2,1,2,2,1,20}
72#define OIDifOutQLen {1,3,6,1,2,1,2,2,1,21}
73#define OIDifSpecific {1,3,6,1,2,1,2,2,1,22}
74#define OIDifType {1,3,6,1,2,1,2,2,1,3}
75#define OIDifMtu {1,3,6,1,2,1,2,2,1,4}
76#define OIDifSpeed {1,3,6,1,2,1,2,2,1,5}
77#define OIDifPhysAddress {1,3,6,1,2,1,2,2,1,6}
78#define OIDifAdminStatus {1,3,6,1,2,1,2,2,1,7}
79#define OIDifOperStatus {1,3,6,1,2,1,2,2,1,8}
80#define OIDifLastChange {1,3,6,1,2,1,2,2,1,9}
81#define OIDat {1,3,6,1,2,1,3}
82#define OIDatTable {1,3,6,1,2,1,3,1}
83#define OIDatEntry {1,3,6,1,2,1,3,1,1}
84#define OIDatIfIndex {1,3,6,1,2,1,3,1,1,1}
85#define OIDatPhysAddress {1,3,6,1,2,1,3,1,1,2}
86#define OIDatNetAddress {1,3,6,1,2,1,3,1,1,3}
87#define OIDip {1,3,6,1,2,1,4}
88#define OIDipForwarding {1,3,6,1,2,1,4,1}
89#define OIDipOutRequests {1,3,6,1,2,1,4,10}
90#define OIDipOutDiscards {1,3,6,1,2,1,4,11}
91#define OIDipOutNoRoutes {1,3,6,1,2,1,4,12}
92#define OIDipReasmTimeout {1,3,6,1,2,1,4,13}
93#define OIDipReasmReqds {1,3,6,1,2,1,4,14}
94#define OIDipReasmOKs {1,3,6,1,2,1,4,15}
95#define OIDipReasmFails {1,3,6,1,2,1,4,16}
96#define OIDipFragOKs {1,3,6,1,2,1,4,17}
97#define OIDipFragFails {1,3,6,1,2,1,4,18}
98#define OIDipFragCreates {1,3,6,1,2,1,4,19}
99#define OIDipDefaultTTL {1,3,6,1,2,1,4,2}
100#define OIDipAddrTable {1,3,6,1,2,1,4,20}
101#define OIDipAddrEntry {1,3,6,1,2,1,4,20,1}
102#define OIDipAdEntAddr {1,3,6,1,2,1,4,20,1,1}
103#define OIDipAdEntIfIndex {1,3,6,1,2,1,4,20,1,2}
104#define OIDipAdEntNetMask {1,3,6,1,2,1,4,20,1,3}
105#define OIDipAdEntBcastAddr {1,3,6,1,2,1,4,20,1,4}
106#define OIDipAdEntReasmMaxSize {1,3,6,1,2,1,4,20,1,5}
107#define OIDipRouteTable {1,3,6,1,2,1,4,21}
108#define OIDipRouteEntry {1,3,6,1,2,1,4,21,1}
109#define OIDipRouteDest {1,3,6,1,2,1,4,21,1,1}
110#define OIDipRouteAge {1,3,6,1,2,1,4,21,1,10}
111#define OIDipRouteMask {1,3,6,1,2,1,4,21,1,11}
112#define OIDipRouteMetric5 {1,3,6,1,2,1,4,21,1,12}
113#define OIDipRouteInfo {1,3,6,1,2,1,4,21,1,13}
114#define OIDipRouteIfIndex {1,3,6,1,2,1,4,21,1,2}
115#define OIDipRouteMetric1 {1,3,6,1,2,1,4,21,1,3}
116#define OIDipRouteMetric2 {1,3,6,1,2,1,4,21,1,4}
117#define OIDipRouteMetric3 {1,3,6,1,2,1,4,21,1,5}
118#define OIDipRouteMetric4 {1,3,6,1,2,1,4,21,1,6}
119#define OIDipRouteNextHop {1,3,6,1,2,1,4,21,1,7}
120#define OIDipRouteType {1,3,6,1,2,1,4,21,1,8}
121#define OIDipRouteProto {1,3,6,1,2,1,4,21,1,9}
122#define OIDipNetToMediaTable {1,3,6,1,2,1,4,22}
123#define OIDipNetToMediaEntry {1,3,6,1,2,1,4,22,1}
124#define OIDipNetToMediaIfIndex {1,3,6,1,2,1,4,22,1,1}
125#define OIDipNetToMediaPhysAddress {1,3,6,1,2,1,4,22,1,2}
126#define OIDipNetToMediaNetAddress {1,3,6,1,2,1,4,22,1,3}
127#define OIDipNetToMediaType {1,3,6,1,2,1,4,22,1,4}
128#define OIDipRoutingDiscards {1,3,6,1,2,1,4,23}
129#define OIDipInReceives {1,3,6,1,2,1,4,3}
130#define OIDipInHdrErrors {1,3,6,1,2,1,4,4}
131#define OIDipInAddrErrors {1,3,6,1,2,1,4,5}
132#define OIDipForwDatagrams {1,3,6,1,2,1,4,6}
133#define OIDipInUnknownProtos {1,3,6,1,2,1,4,7}
134#define OIDipInDiscards {1,3,6,1,2,1,4,8}
135#define OIDipInDelivers {1,3,6,1,2,1,4,9}
136#define OIDicmp {1,3,6,1,2,1,5}
137#define OIDicmpInMsgs {1,3,6,1,2,1,5,1}
138#define OIDicmpInTimestamps {1,3,6,1,2,1,5,10}
139#define OIDicmpInTimestampReps {1,3,6,1,2,1,5,11}
140#define OIDicmpInAddrMasks {1,3,6,1,2,1,5,12}
141#define OIDicmpInAddrMaskReps {1,3,6,1,2,1,5,13}
142#define OIDicmpOutMsgs {1,3,6,1,2,1,5,14}
143#define OIDicmpOutErrors {1,3,6,1,2,1,5,15}
144#define OIDicmpOutDestUnreachs {1,3,6,1,2,1,5,16}
145#define OIDicmpOutTimeExcds {1,3,6,1,2,1,5,17}
146#define OIDicmpOutParmProbs {1,3,6,1,2,1,5,18}
147#define OIDicmpOutSrcQuenchs {1,3,6,1,2,1,5,19}
148#define OIDicmpInErrors {1,3,6,1,2,1,5,2}
149#define OIDicmpOutRedirects {1,3,6,1,2,1,5,20}
150#define OIDicmpOutEchos {1,3,6,1,2,1,5,21}
151#define OIDicmpOutEchoReps {1,3,6,1,2,1,5,22}
152#define OIDicmpOutTimestamps {1,3,6,1,2,1,5,23}
153#define OIDicmpOutTimestampReps {1,3,6,1,2,1,5,24}
154#define OIDicmpOutAddrMasks {1,3,6,1,2,1,5,25}
155#define OIDicmpOutAddrMaskReps {1,3,6,1,2,1,5,26}
156#define OIDicmpInDestUnreachs {1,3,6,1,2,1,5,3}
157#define OIDicmpInTimeExcds {1,3,6,1,2,1,5,4}
158#define OIDicmpInParmProbs {1,3,6,1,2,1,5,5}
159#define OIDicmpInSrcQuenchs {1,3,6,1,2,1,5,6}
160#define OIDicmpInRedirects {1,3,6,1,2,1,5,7}
161#define OIDicmpInEchos {1,3,6,1,2,1,5,8}
162#define OIDicmpInEchoReps {1,3,6,1,2,1,5,9}
163#define OIDtcp {1,3,6,1,2,1,6}
164#define OIDtcpRtoAlgorithm {1,3,6,1,2,1,6,1}
165#define OIDtcpInSegs {1,3,6,1,2,1,6,10}
166#define OIDtcpOutSegs {1,3,6,1,2,1,6,11}
167#define OIDtcpRetransSegs {1,3,6,1,2,1,6,12}
168#define OIDtcpConnTable {1,3,6,1,2,1,6,13}
169#define OIDtcpConnEntry {1,3,6,1,2,1,6,13,1}
170#define OIDtcpConnState {1,3,6,1,2,1,6,13,1,1}
171#define OIDtcpConnLocalAddress {1,3,6,1,2,1,6,13,1,2}
172#define OIDtcpConnLocalPort {1,3,6,1,2,1,6,13,1,3}
173#define OIDtcpConnRemAddress {1,3,6,1,2,1,6,13,1,4}
174#define OIDtcpConnRemPort {1,3,6,1,2,1,6,13,1,5}
175#define OIDtcpInErrs {1,3,6,1,2,1,6,14}
176#define OIDtcpOutRsts {1,3,6,1,2,1,6,15}
177#define OIDtcpRtoMin {1,3,6,1,2,1,6,2}
178#define OIDtcpRtoMax {1,3,6,1,2,1,6,3}
179#define OIDtcpMaxConn {1,3,6,1,2,1,6,4}
180#define OIDtcpActiveOpens {1,3,6,1,2,1,6,5}
181#define OIDtcpPassiveOpens {1,3,6,1,2,1,6,6}
182#define OIDtcpAttemptFails {1,3,6,1,2,1,6,7}
183#define OIDtcpEstabResets {1,3,6,1,2,1,6,8}
184#define OIDtcpCurrEstab {1,3,6,1,2,1,6,9}
185#define OIDudp {1,3,6,1,2,1,7}
186#define OIDudpInDatagrams {1,3,6,1,2,1,7,1}
187#define OIDudpNoPorts {1,3,6,1,2,1,7,2}
188#define OIDudpInErrors {1,3,6,1,2,1,7,3}
189#define OIDudpOutDatagrams {1,3,6,1,2,1,7,4}
190#define OIDudpTable {1,3,6,1,2,1,7,5}
191#define OIDudpEntry {1,3,6,1,2,1,7,5,1}
192#define OIDudpLocalAddress {1,3,6,1,2,1,7,5,1,1}
193#define OIDudpLocalPort {1,3,6,1,2,1,7,5,1,2}
194#define OIDegp {1,3,6,1,2,1,8}
195#define OIDegpInMsgs {1,3,6,1,2,1,8,1}
196#define OIDegpInErrors {1,3,6,1,2,1,8,2}
197#define OIDegpOutMsgs {1,3,6,1,2,1,8,3}
198#define OIDegpOutErrors {1,3,6,1,2,1,8,4}
199#define OIDegpNeighTable {1,3,6,1,2,1,8,5}
200#define OIDegpNeighEntry {1,3,6,1,2,1,8,5,1}
201#define OIDegpNeighState {1,3,6,1,2,1,8,5,1,1}
202#define OIDegpNeighStateUps {1,3,6,1,2,1,8,5,1,10}
203#define OIDegpNeighStateDowns {1,3,6,1,2,1,8,5,1,11}
204#define OIDegpNeighIntervalHello {1,3,6,1,2,1,8,5,1,12}
205#define OIDegpNeighIntervalPoll {1,3,6,1,2,1,8,5,1,13}
206#define OIDegpNeighMode {1,3,6,1,2,1,8,5,1,14}
207#define OIDegpNeighEventTrigger {1,3,6,1,2,1,8,5,1,15}
208#define OIDegpNeighAddr {1,3,6,1,2,1,8,5,1,2}
209#define OIDegpNeighAs {1,3,6,1,2,1,8,5,1,3}
210#define OIDegpNeighInMsgs {1,3,6,1,2,1,8,5,1,4}
211#define OIDegpNeighInErrs {1,3,6,1,2,1,8,5,1,5}
212#define OIDegpNeighOutMsgs {1,3,6,1,2,1,8,5,1,6}
213#define OIDegpNeighOutErrs {1,3,6,1,2,1,8,5,1,7}
214#define OIDegpNeighInErrMsgs {1,3,6,1,2,1,8,5,1,8}
215#define OIDegpNeighOutErrMsgs {1,3,6,1,2,1,8,5,1,9}
216#define OIDegpAs {1,3,6,1,2,1,8,6}
217#define OIDexperimental {1,3,6,1,3}
218#define OIDprivate {1,3,6,1,4}
219#define OIDenterprises {1,3,6,1,4,1}
220
221 #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 @@
1 #ifndef__SNMPEER_H
2#define __SNMPEER_H
3
4namespace Klever {
5
6 class CASNAny{
7public:
8 enum{
9 asnCls = 0xC0,
10 asnClsUniversal = 0x00,
11 asnClsApplication = 0x40,
12 asnClsContextSpecific = 0x80,
13 asnClsPrivate = 0xC0,
14 asnConstructed = 0x20,
15 asnPrimitive = 0x00,
16 asnTag = 0x1F,
17 // ASN.1 Primitive Tags
18 asnTagInteger = 0x02,
19 asnTagOctetString = 0x04,
20 asnTagNull = 0x05,
21 asnTagOID = 0x06,
22 // ASN.1 Constructed Tags
23 asnTagSequence = 0x10,
24 // RFC1155 Primitive Tags
25 asnTagIP = 0x00,
26 asnTagCounter = 0x01,
27 asnTagGauge = 0x02,
28 asnTagTicks = 0x03,
29 asnTagOpaque = 0x04,
30 // RFC1213 alias
31 asnTagDispString = 0x04,// (ASN.1 Octet string)
32 // RFC1157 Constructed Tags
33 asnTagGetRequest = 0x00,
34 asnTagGetNextRequest = 0x01,
35 asnTagGetResponse = 0x02,
36 asnTagSetRequest = 0x03,
37 asnTagTrap = 0x04
38 };
39 enum{
40 typeASNInteger = (asnClsUniversal|asnPrimitive|asnTagInteger),
41 typeASNOctetString = (asnClsUniversal|asnPrimitive|asnTagOctetString),
42 typeASNNull = (asnClsUniversal|asnPrimitive|asnTagNull),
43 typeASNOID = (asnClsUniversal|asnPrimitive|asnTagOID),
44
45 typeASNSequence = (asnClsUniversal|asnConstructed|asnTagSequence),
46 typeASNSequenceOf = (asnClsUniversal|asnConstructed|asnTagSequence),
47
48 typeASNIP = (asnClsApplication|asnPrimitive|asnTagIP),
49 typeASNCounter = (asnClsApplication|asnPrimitive|asnTagCounter),
50 typeASNGauge = (asnClsApplication|asnPrimitive|asnTagGauge),
51 typeASNTicks = (asnClsApplication|asnPrimitive|asnTagTicks),
52 typeASNOpaque = (asnClsApplication|asnPrimitive|asnTagOpaque),
53 typeASNDispString = (asnClsUniversal|asnPrimitive|asnTagOctetString),
54
55 typeASNGetRequest = (asnClsContextSpecific|asnConstructed|asnTagGetRequest),
56 typeASNGetNextRequest = (asnClsContextSpecific|asnConstructed|asnTagGetNextRequest),
57 typeASNGetResponse = (asnClsContextSpecific|asnConstructed|asnTagGetResponse),
58 typeASNSetRequest = (asnClsContextSpecific|asnConstructed|asnTagSetRequest),
59 typeASNTrap = (asnClsContextSpecific|asnConstructed|asnTagTrap)
60 };
61
62 typedefLONG asnInteger;
63 typedef LARGE_INTEGER asnInteger64;
64 typedefDWORD asnCounter;
65 typedef ULARGE_INTEGER asnCounter64;
66 typedef DWORD asnGauge;
67 typedef ULARGE_INTEGER asnGauge64;
68 typedefDWORD asnTicks;
69 typedef ULARGE_INTEGER asnTicks64;
70 struct asnDynamic{
71 UINT size;
72 LPBYTE data;
73 BOOL Allocate(UINT size) {
74 BOOL rv = Free();
75 if(size)
76 rv=rv&&(data=new BYTE[size]);
77 if(rv)
78 asnDynamic::size=size;
79 return rv;
80 }
81 BOOL Set(LPBYTE data,UINT size) {
82 BOOL rv = Allocate(size);
83 if(rv && size)
84 memmove(asnDynamic::data,data,size);
85 return rv;
86 }
87 BOOL Free() {
88 if(!size)
89 return TRUE;
90 delete data;
91 size=0;
92 data=0;
93 return TRUE;
94 }
95 void Clean() {
96 size=0;
97 data=0;
98 }
99 BOOL Copy(asnDynamic& src) {
100 BOOL rv = Free();
101 if(rv){
102 if(src.size)
103 rv=rv&&(data = new BYTE[src.size]);
104 if(rv){
105 if(size=src.size)
106 memmove(data,src.data,size);
107 }
108 }
109 return rv;
110 }
111 };
112 typedefasnDynamic asnOctetString;
113 typedef asnDynamic asnOID;
114 typedef in_addr asnIP;
115 typedef asnDynamic asnSequence;
116
117 BYTE type;
118 enum _storeType{
119 storeDynamic,
120 storeStatic
121 }storeType;
122 union{
123 asnInteger number;
124 asnInteger64 number64;
125 asnOctetString string;
126 asnOID oid;
127 asnSequence sequence;
128 asnIP ip;
129 asnCounter counter;
130 asnCounter64 counter64;
131 asnGauge gauge;
132 asnGauge64 gauge64;
133 asnTicks ticks;
134 asnTicks64 ticks64;
135 asnDynamic data;
136 } value;
137
138 CASNAny() : type(typeASNNull), storeType(storeStatic) { value.data.Clean(); }
139 CASNAny(CASNAny& src) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Copy(src); }
140 CASNAny(BYTE type) : type(type), storeType(storeStatic) { value.data.Clean(); }
141 CASNAny(BYTE type,LONG number) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,number); }
142 CASNAny(BYTE type,LONGLONG number) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,number); }
143 CASNAny(BYTE type,LPCTSTR string) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,string); }
144 CASNAny(BYTE type,LPBYTE data,UINT length) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,data,length); }
145 CASNAny(BYTE type,UINT* data,UINT size) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(type,(LPBYTE)data,size); }
146 CASNAny(in_addr& ip) : type(typeASNNull), storeType(storeStatic) { value.data.Clean();Set(ip); }
147 ~CASNAny() { Free(); }
148
149 BOOL Set(BYTE type) {
150 BOOL rv = Free();
151 CASNAny::type=type;
152 return rv;
153 }
154 BOOL Set(BYTE type,LONG number) {
155 BOOL rv = Free();
156 CASNAny::type=type;
157 value.number=number;
158 storeType=storeStatic;
159 return rv;
160 }
161 BOOL Set(BYTE type,LONGLONG number) {
162 BOOL rv = Free();
163 CASNAny::type=type;
164 value.number64.QuadPart = number;
165 storeType=storeStatic;
166 return rv;
167 }
168 BOOL Set(BYTE type,LPCTSTR string) {
169 BOOL rv = Free();
170 CASNAny::type=type;
171 rv=rv&&value.string.Set((LPBYTE)string,strlen(string)+1);
172 if(rv){
173 value.string.size--;
174 storeType=storeDynamic;
175 }
176 return rv;
177 }
178 BOOL Set(BYTE type,LPBYTE data,UINT length) {
179 BOOL rv = Free();
180 CASNAny::type=type;
181 rv=rv&&value.data.Set(data,length);
182 if(rv)
183 storeType=storeDynamic;
184 return rv;
185 }
186 BOOL Set(in_addr& ip) {
187 BOOL rv = Free();
188 memmove(&value.ip,&ip,sizeof(value.ip));
189 type=typeASNIP;
190 storeType=storeStatic;
191 return rv;
192 }
193 BOOL Free() {
194 if(storeType==storeDynamic)
195 value.data.Free();
196 else{
197 memset(&value,0,sizeof(value));
198 value.data.Clean();
199 }
200 storeType=storeStatic;
201 type=typeASNNull;
202 return TRUE;
203 }
204 BOOL Copy(CASNAny& src) {
205 BOOL rv = Free();
206 if(src.storeType==storeDynamic){
207 rv=rv&&value.data.Copy(src.value.data);
208 if(rv){
209 type=src.type;
210 storeType=src.storeType;
211 }
212 }else{
213 memmove(this,&src,sizeof(*this));
214 }
215 return rv;
216 }
217 CASNAny& operator=(CASNAny& src) {
218 VERIFY(Copy(src));
219 return *this;
220 }
221
222 // High Level
223 CString GetString() {
224 ASSERT(storeType==storeDynamic);
225 CString rv;
226 LPTSTR b = rv.GetBuffer(value.data.size+1);
227 ASSERT(b);
228 b[value.data.size]=0;
229 memmove(b,value.data.data,value.data.size);
230 rv.ReleaseBuffer();
231 return rv;
232 }
233};
234
235
236 class CSNMPVarBind{
237public:
238 CASNAny name;
239 CASNAny value;
240
241 CSNMPVarBind() {}
242 CSNMPVarBind(CASNAny& name,CASNAny& value) : name(name), value(value) {}
243 CSNMPVarBind(CASNAny& name) : name(name) {}
244 CSNMPVarBind(CSNMPVarBind& src) { Copy(src); }
245 BOOL Copy(CSNMPVarBind& src) {
246 name.Copy(src.name);
247 value.Copy(src.value);
248 return TRUE;
249 }
250 CSNMPVarBind& operator=(CSNMPVarBind& src) {
251 Copy(src);
252 return *this;
253 }
254 // High level
255 BOOL IsName(UINT* prefix,UINT prefixSize,BOOL bExact=FALSE) {
256 if(name.type!=CASNAny::typeASNOID)
257 return FALSE;
258 if(name.value.oid.size<prefixSize)
259 return FALSE;
260 if(bExact && (name.value.oid.size!=prefixSize))
261 return FALSE;
262 return !memcmp(prefix,name.value.oid.data,prefixSize);
263 }
264};
265
266 class CSNMPVarBindList: public CList<CSNMPVarBind,CSNMPVarBind&> {
267public:
268 CSNMPVarBind* GetVarBind(UINT* prefix,UINT prefixSize,BOOL bExact=FALSE) {
269 POSITION p = GetHeadPosition();
270 while(p){
271 CSNMPVarBind& vb = GetNext(p);
272 if(vb.IsName(prefix,prefixSize,bExact))
273 return &vb;
274 }
275 return NULL;
276 }
277};
278
279 class CSNMPeer{
280public:
281 virtual BOOL Request(BYTE type,CSNMPVarBindList& in,CSNMPVarBindList& ou) = 0;
282};
283
284};
285
286 #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 @@
1 #defineWIN32_LEAN_AND_MEAN
2#define VC_EXTRALEAN
3#define WIN32_EXTRALEAN
4#include <windows.h>
5#include <shlobj.h>
6#include <winver.h>
7#include <crtdbg.h>
8#include <string.h>
9#include <stdio.h>
10
11extern "C" WINSHELLAPI void WINAPI SHFree( LPVOID);
12
13 template<class T> class Smart{
14public:
15 T *pT;
16
17 Smart() : pT(NULL) {}
18 Smart(int cb) : pT(new T[cb]) {}
19 Smart(T* p) : pT(p) {}
20 ~Smart() { if(pT)delete pT; }
21
22 Smart& operator=(T* p) { if(pT)delete pT; pT=p; return *this; }
23 operator T* () { return pT; }
24
25 //T& operator[](int ndx) { return pT[ndx]; }
26
27 T* Detach() { T* rv = pT; pT=NULL; return rv; }
28};
29 typedefSmart<char> STRING;
30
31 #define APPEND_SLASH(str) if((str)[strlen(str)-1]!='\\')strcat(str,"\\")
32
33HINSTANCE theInstance;
34
35LPSTR strFETCH_REG_KEY(HKEY hRoot,LPCSTR subKey,LPCSTR val)
36{
37HKEY hkey;
38 if(RegOpenKeyEx(hRoot,subKey,0,KEY_QUERY_VALUE,&hkey)!=ERROR_SUCCESS)
39 return NULL;
40DWORD kType,cb=0;
41STRING rv;
42 if(RegQueryValueEx(hkey,val,NULL,&kType,NULL,&cb)==ERROR_SUCCESS && kType==REG_SZ){
43 rv= new char[cb];
44 _ASSERT(rv!=NULL);
45 if(RegQueryValueEx(hkey,val,NULL,&kType,(LPBYTE)(LPSTR)rv,&cb)!=ERROR_SUCCESS)
46 rv=NULL;
47 }
48 RegCloseKey(hkey);
49 return rv.Detach();
50}
51
52BOOL strSET_REG_KEY(HKEY hRoot,LPCSTR subKey,LPCSTR valName,LPCSTR val)
53{
54HKEY hkey;
55DWORD dw;
56 if(RegCreateKeyEx(hRoot,subKey,0,REG_NONE,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&hkey,&dw)!=ERROR_SUCCESS)
57 return FALSE;
58BOOL rv = (RegSetValueEx(hkey,valName,0,REG_SZ,(LPBYTE)val,strlen(val)+1)==ERROR_SUCCESS);
59 RegCloseKey(hkey);
60 return rv;
61}
62
63void MAKE_PATH(LPCSTR path)
64{
65STRING tmp(strlen(path)+1);
66LPCSTR t0=path;
67LPSTR t1=tmp;
68 while(*t0){
69 if((*t0)=='\\'){
70 *t1=0;
71 CreateDirectory(tmp,NULL);
72 }
73 *(t1++)=*(t0++);
74 }
75 *t1=0;
76 CreateDirectory(tmp,NULL);
77}
78
79BOOL ADDMENU(LPCSTR menu,LPCSTR item,LPCSTR path,LPCSTR program)
80{
81STRING stm = strFETCH_REG_KEY(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders","Programs");
82 if(!stm)
83 return FALSE;
84int pil = 1+strlen(path)+1+strlen(program)+1+1;
85STRING pi(pil);
86 strcpy(pi,path);
87 APPEND_SLASH(pi);
88 strcat(pi,program);
89int ipl = strlen(stm)+1+strlen(menu)+1+strlen(item)+4+1;
90STRING ip(ipl);
91 memmove(ip,stm,strlen(stm)+1);
92 APPEND_SLASH(ip);
93 strcat(ip,menu);
94 MAKE_PATH(ip);
95 APPEND_SLASH(ip);
96 strcat(ip,item);
97 strcat(ip,".lnk");
98IShellLink* sl = NULL;
99IPersistFile* pf = NULL;
100BOOL rv = FALSE;
101 do{
102 HRESULT hrv = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&sl);
103 if(!SUCCEEDED(hrv))
104 break;
105 sl->SetDescription(item);
106 sl->SetPath(pi);
107 hrv = sl->QueryInterface(IID_IPersistFile,(LPVOID*)&pf);
108 if(!SUCCEEDED(hrv))
109 break;
110 WORD wsz[MAX_PATH];
111 MultiByteToWideChar(CP_ACP,0,ip,-1,wsz,MAX_PATH);
112 hrv = pf->Save(wsz,TRUE);
113 if(SUCCEEDED(hrv))
114 rv=TRUE;
115 }while(FALSE);
116 if(pf)
117 pf->Release();
118 if(sl)
119 sl->Release();
120 return rv;
121}
122
123FILE* CREATE_INF_FILE(LPCSTR path,LPCSTR file)
124{
125STRING fn(strlen(path)+1+strlen(file)+1);
126 strcpy(fn,path);
127 APPEND_SLASH(fn);
128 strcat(fn,file);
129 return fopen(fn,"wt");
130}
131
132BOOL INSTALLFILE(LPCSTR res,LPCSTR path,LPCSTR file)
133{
134STRING temp(MAX_PATH);
135 if(!GetTempPath(MAX_PATH,temp)) return FALSE;
136STRING tf(MAX_PATH);
137 if(!GetTempFileName(temp,"KGI",0,tf)) return FALSE;
138HRSRC hrsrc = FindResource(NULL,res,MAKEINTRESOURCE(RT_RCDATA));
139 if(!hrsrc) return FALSE;
140DWORD sor = SizeofResource(NULL,hrsrc);
141 if(!sor) return FALSE;
142HGLOBAL hglobal = LoadResource(NULL,hrsrc);
143 if(!hglobal) return FALSE;
144LPVOID lpv = LockResource(hglobal);
145 if(!lpv) return FALSE;
146HANDLE hf = CreateFile(tf,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY,NULL);
147 if(!hf) return FALSE;
148DWORD written = 0;
149 if(!WriteFile(hf,lpv,sor,&written,NULL) || written!=sor){
150 CloseHandle(hf);
151 return FALSE;
152 }
153 CloseHandle(hf);
154STRING toKill(strlen(tf)+1);
155 strcpy(toKill,tf);
156 for(int tmp=strlen(tf)-1;tmp>0 && ((tf[tmp])!='\\');tmp--);
157 if(tf[tmp]=='\\')
158 tf[tmp++]=0;
159STRING nothing(_MAX_PATH);
160UINT nothingLength=_MAX_PATH;
161 if(VerInstallFile(0,&tf[tmp],(LPSTR)file,tf,(LPSTR)path,NULL,nothing,&nothingLength)){
162 DeleteFile(toKill);
163 return FALSE;
164 }
165 DeleteFile(toKill);
166 return TRUE;
167}
168
169LPCSTR pdTitle, pdPrompt;
170char pdPath[_MAX_PATH];
171BOOL CALLBACK pathDlgProc(HWND hwnd,UINT uMsg,WPARAM wP,LPARAM lP)
172{
173 switch(uMsg){
174 case WM_INITDIALOG:
175 SetWindowText(hwnd,pdTitle);
176 SetDlgItemText(hwnd,IDC_PROMPT,pdPrompt);
177 SetDlgItemText(hwnd,IDC_PATH,pdPath);
178 SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
179 return 1;
180 case WM_COMMAND:
181 switch(LOWORD(wP)){ // ID
182 case IDC_BROWSE:
183 switch(HIWORD(wP)){
184 case BN_CLICKED:
185 {
186 BROWSEINFO bi;
187 memset(&bi,0,sizeof(bi));
188 bi.hwndOwner=hwnd;
189 bi.pszDisplayName=pdPath;
190 bi.lpszTitle="Select Folder..";
191 bi.ulFlags=BIF_RETURNONLYFSDIRS;
192 LPITEMIDLIST lpidl=SHBrowseForFolder(&bi);
193 if(lpidl){
194 SHGetPathFromIDList(lpidl,pdPath);
195 SHFree(lpidl);
196 SetDlgItemText(hwnd,IDC_PATH,pdPath);
197 }
198 }
199 return 1;
200 }
201 break;
202 case IDOK:
203 switch(HIWORD(wP)){
204 case BN_CLICKED:
205 if(GetDlgItemText(hwnd,IDC_PATH,pdPath,sizeof(pdPath)))
206 EndDialog(hwnd,IDOK);
207 else
208 // *** Error message
209 EndDialog(hwnd,IDCANCEL);
210 return 1;
211 }
212 break;
213 case IDCANCEL:
214 switch(HIWORD(wP)){
215 case BN_CLICKED:
216 EndDialog(hwnd,IDCANCEL);
217 return 1;
218 }
219 break;
220 };
221 break;
222 }
223 return 0;
224}
225
226LPSTR REQUESTPATH(LPCSTR title,LPCSTR prompt,LPCSTR defPath)
227{
228 pdTitle=title;pdPrompt=prompt;
229 strcpy(pdPath,defPath);
230 if(DialogBox(NULL,MAKEINTRESOURCE(IDD_PATH),NULL/*Parent*/,(DLGPROC)&pathDlgProc)!=IDOK)
231 return NULL;
232STRING rv(strlen(pdPath)+1);
233 strcpy(rv,pdPath);
234 return rv.Detach();
235}
236
237HKEY uninstallKey(LPCSTR regKey) {
238 STRING rk(100+strlen(regKey)+1);
239 sprintf(rk,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s",regKey);
240 HKEY rv = NULL;
241 DWORD dw;
242 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,rk,0,REG_NONE,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&rv,&dw)!=ERROR_SUCCESS)
243 return NULL;
244 return rv;
245}
246
247BOOL REG_UNINSTALL_COMMAND(LPCSTR regKey,LPCSTR dName,LPCSTR iPath,LPCSTR iFile,LPCSTR iSection)
248{
249 HKEY hKey = uninstallKey(regKey);
250 if(!hKey)
251 return FALSE;
252 BOOL rv=FALSE;
253 do{
254 if(RegSetValueEx(hKey,"DisplayName",0,REG_SZ,(LPBYTE)dName,strlen(dName)+1)!=ERROR_SUCCESS)
255 break;
256 STRING us(50+strlen(iPath)+1+strlen(iFile)+strlen(iSection)+1);
257 strcpy(us,"RunDll32 setupapi.dll,InstallHinfSection ");
258 strcat(us,iSection);
259 strcat(us," 132 ");
260 strcat(us,iPath);
261 APPEND_SLASH(us);
262 strcat(us,iFile);
263 if(RegSetValueEx(hKey,"UninstallString",0,REG_SZ,(LPBYTE)(LPCSTR)us,strlen(us)+1)!=ERROR_SUCCESS)
264 break;
265 rv=TRUE;
266 }while(FALSE);
267 RegCloseKey(hKey);
268 return rv;
269}
270BOOL REG_UNINSTALL_ICON(LPCSTR regKey,LPCSTR path,LPCSTR file,int n) {
271 HKEY hKey = uninstallKey(regKey);
272 if(!hKey)
273 return FALSE;
274 STRING uis(strlen(path)+1+strlen(file)+7);
275 strcpy(uis,path);
276 APPEND_SLASH(uis);
277 strcat(uis,file);
278 char tmp[8];
279 sprintf(tmp,";%d",n);
280 strcat(uis,tmp);
281 BOOL rv = TRUE;
282 if(RegSetValueEx(hKey,"DisplayIcon",0,REG_SZ,(LPBYTE)(LPCSTR)uis,strlen(uis)+1)!=ERROR_SUCCESS)
283 rv = FALSE;
284 RegCloseKey(hKey);
285 return rv;
286}
287BOOL REG_UNINSTALL_COMMENT(LPCSTR regKey,LPCSTR comment) {
288 HKEY hKey = uninstallKey(regKey);
289 if(!hKey)
290 return FALSE;
291 BOOL rv = TRUE;
292 if(RegSetValueEx(hKey,"lComment",0,REG_SZ,(LPBYTE)comment,strlen(comment)+1)!=ERROR_SUCCESS)
293 rv = FALSE;
294 RegCloseKey(hKey);
295 return rv;
296}
297BOOL REG_UNINSTALL_VERSION(LPCSTR regKey,LPCSTR version) {
298 HKEY hKey = uninstallKey(regKey);
299 if(!hKey)
300 return FALSE;
301 BOOL rv = TRUE;
302 if(RegSetValueEx(hKey,"DisplayVersion",0,REG_SZ,(LPBYTE)version,strlen(version)+1)!=ERROR_SUCCESS)
303 rv = FALSE;
304 RegCloseKey(hKey);
305 return rv;
306}
307BOOL REG_UNINSTALL_LOCATION(LPCSTR regKey,LPCSTR location) {
308 HKEY hKey = uninstallKey(regKey);
309 if(!hKey)
310 return FALSE;
311 BOOL rv = TRUE;
312 if(RegSetValueEx(hKey,"InstallLocation",0,REG_SZ,(LPBYTE)location,strlen(location)+1)!=ERROR_SUCCESS)
313 rv = FALSE;
314 RegCloseKey(hKey);
315 return rv;
316}
317BOOL REG_UNINSTALL_PUBLISHER(LPCSTR regKey,LPCSTR publisher) {
318 HKEY hKey = uninstallKey(regKey);
319 if(!hKey)
320 return FALSE;
321 BOOL rv = TRUE;
322 if(RegSetValueEx(hKey,"Publisher",0,REG_SZ,(LPBYTE)publisher,strlen(publisher)+1)!=ERROR_SUCCESS)
323 rv = FALSE;
324 RegCloseKey(hKey);
325 return rv;
326}
327BOOL REG_UNINSTALL_URLS(LPCSTR regKey,LPCSTR about,LPCSTR update) {
328 HKEY hKey = uninstallKey(regKey);
329 if(!hKey)
330 return FALSE;
331 BOOL rv = TRUE;
332 if(RegSetValueEx(hKey,"URLInfoAbout",0,REG_SZ,(LPBYTE)about,strlen(about)+1)!=ERROR_SUCCESS)
333 rv = FALSE;
334 if(RegSetValueEx(hKey,"URLUpdateInfo",0,REG_SZ,(LPBYTE)update,strlen(update)+1)!=ERROR_SUCCESS)
335 rv = FALSE;
336 RegCloseKey(hKey);
337 return rv;
338}
339
340 #defineINF_FILE_HEADER(i) fprintf(i,"[Version]\nSignature=\"$CHICAGO$\"\n\n")
341#define INF_FILE_SECTION(i,s) fprintf(i,"\n[%s]\n",s)
342 #defineINF_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)
343#define INF_MENU_GROUP(i,n,m) fprintf(i,"setup.ini, progman.groups,,\"group%d=%s\"\n",n,m)
344#define INF_MENU_ITEM(i,n,m) fprintf(i,"setup.ini, group%d,, \"\"\"%s\"\"\"\n",n,m);
345#define INF_REMOVE_ROOT(i,g,r) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\DeleteFiles\\%s,,,\"%s\"\n",g,r)
346#define INF_REMOVE_FILE(i,g,f) fprintf(i,"HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\DeleteFiles\\%s,%s,,\"%s\"\n",g,f,f)
347#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");}
348
349LPSTR GET_SHORT_PATH(LPCSTR path)
350{
351char tmp;
352DWORD len = GetShortPathName(path,&tmp,1);
353 if(!len)
354 return NULL;
355STRING rv(len+1);
356 if(!GetShortPathName(path,rv,len+1))
357 return NULL;
358 return rv.Detach();
359}
360
361BOOL Install(void);
362
363int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)
364{
365 theInstance=hInstance;
366 CoInitialize(NULL);
367 Install();
368 CoUninitialize();
369 return 0;
370}
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 @@
1#ifndef IP_ICMPHEADER
2
3#define IP_ICMPHEADER
4
5struct icmp {
6 BYTE icmp_type;
7 BYTE icmp_code;
8 WORD icmp_cksum;
9 WORD icmp_id;
10 WORD icmp_seq;
11 char icmp_data[1];
12};
13
14#define SIZE_ICMP_HDR 8
15#define SIZE_TIME_DATA 8
16
17struct ip {
18 BYTE ip_hl:4, /* header length */
19 ip_v:4; /* version */
20 BYTE ip_tos; /* type of service */
21 short ip_len; /* total length */
22 u_short ip_id; /* identification */
23 short ip_off; /* fragment offset field */
24 BYTE ip_ttl; /* time to live */
25 BYTE ip_p; /* protocol */
26 u_short ip_sum; /* checksum */
27 struct in_addr ip_src,ip_dst; /* source and dest address */
28};
29
30#define ICMP_ECHOREPLY 0 /* echo reply */
31#define ICMP_UNREACH 3 /* dest unreachable, codes: */
32#define ICMP_UNREACH_NET 0 /* bad net */
33#define ICMP_UNREACH_HOST 1 /* bad host */
34#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
35#define ICMP_UNREACH_PORT 3 /* bad port */
36#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
37#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
38#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
39#define ICMP_REDIRECT 5 /* shorter route, codes: */
40#define ICMP_REDIRECT_NET 0 /* for network */
41#define ICMP_REDIRECT_HOST 1 /* for host */
42#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
43#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
44#define ICMP_ECHO 8 /* echo service */
45#define ICMP_TIMXCEED 11 /* time exceeded, code: */
46#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
47#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
48#define ICMP_PARAMPROB 12 /* ip header bad */
49#define ICMP_TSTAMP 13 /* timestamp request */
50#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
51#define ICMP_IREQ 15 /* information request */
52#define ICMP_IREQREPLY 16 /* information reply */
53#define ICMP_MASKREQ 17 /* address mask request */
54#define ICMP_MASKREPLY 18 /* address mask reply */
55
56#define ICMP_MAXTYPE 18
57
58#define ICMP_MINLEN 8 /* abs minimum */
59#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
60#define ICMP_MASKLEN 12 /* address mask */
61#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
62#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
63
64#define STNORM 0
65
66/* Definition of the lowest telnet byte following an IAC byte */
67#define LOW_TEL_OPT 236
68
69#define TEL_EOF 236
70#define SUSP 237
71#define ABORT 238
72
73#define SE 240
74#define NOP 241
75#define DM 242
76#define BREAK 243
77#define IP 244
78#define AO 245
79#define AYT 246
80#define EC 247
81#define EL 248
82#define GOAHEAD 249
83#define SB 250
84#define WILL 251
85#define WONT 252
86#define DO 253
87#define DONT 254
88#define IAC 255
89
90#endif
91
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 @@
1 #ifndef__KHELPERS_H
2#define __KHELPERS_H
3
4#include <shlobj.h>
5
6extern "C" WINSHELLAPI void WINAPI SHFree( LPVOID);
7
8namespace Klever {
9
10 inline BOOL BrowseForFolder(CString& folder,LPCTSTR title=NULL,CWnd* pParent=NULL) {
11 BROWSEINFO bi;
12 memset(&bi,0,sizeof(bi));
13 if(pParent)
14 bi.hwndOwner=pParent->GetSafeHwnd();
15 CString rv;
16 bi.pszDisplayName=rv.GetBuffer(MAX_PATH);
17 bi.lpszTitle=title;
18 bi.ulFlags=BIF_RETURNONLYFSDIRS;
19 LPITEMIDLIST lpidl = SHBrowseForFolder(&bi);
20 if(lpidl){
21 SHGetPathFromIDList(lpidl,bi.pszDisplayName);
22 SHFree(lpidl);
23 rv.ReleaseBuffer();
24 folder=rv;
25 return TRUE;
26 }
27 rv.ReleaseBuffer();
28 return FALSE;
29 }
30 inline BOOL BrowseForFolder(CString& folder,UINT idTitle,CWnd* pParent=NULL) {
31 CString title;
32 VERIFY(title.LoadString(idTitle));
33 return BrowseForFolder(folder,title,pParent);
34 }
35 inline CString GluePathAndFile(LPCTSTR path,LPCTSTR file) {
36 CString rv = path;
37 while((!rv.IsEmpty()) && rv[rv.GetLength()-1]=='\\')
38 rv=rv.Left(rv.GetLength()-1);
39 rv+='\\';
40 while(*file && *file=='\\')
41 file++;
42 rv+=file;
43 return rv;
44 }
45 inline UINT TokenizeString(CStringList& rv,LPCTSTR string,LPCTSTR delimiter) {
46 CString s = string;
47 int found;
48 int delength = strlen(delimiter);
49 int rvc = 0;
50 while((found=s.Find(delimiter))>=0){
51 rv.AddTail(s.Left(found));
52 rvc++;
53 s=s.Mid(found+delength);
54 }
55 if(!s.IsEmpty()){
56 rv.AddTail(s);
57 rvc++;
58 }
59 return rvc;
60 }
61 inline BOOL LogRecord(LPCTSTR logFile,LPCTSTR logRecord) {
62 try{
63 CFile f(logFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyWrite);
64 f.SeekToEnd();
65 CString s = CTime::GetCurrentTime().Format("[%c] ")+logRecord+"\r\n";
66 f.Write((LPCTSTR)s,s.GetLength());
67 }catch(CException* e){
68 e->Delete();
69 return FALSE;
70 }
71 return TRUE;
72 }
73 inline BOOL ReadString(CFile* file,CString& rv) {
74 rv.Empty();
75 int nBuffer = 256;
76 TCHAR* ch = rv.GetBuffer(nBuffer);
77 int nPos = 0;
78 BOOL bRV = FALSE;
79 for(;;){
80 TCHAR c;
81 try{
82 if(file->Read(&c,sizeof(c))!=sizeof(c))
83 break;
84 bRV=TRUE;
85 }catch(CException* e){
86 e->Delete();
87 TRACE0("Exception in ReadString\n");
88 return FALSE;
89 }
90 if(nPos>=(nBuffer-1)){
91 rv.ReleaseBuffer();
92 ch = rv.GetBuffer(nBuffer=nBuffer+256);
93 ASSERT(ch);
94 }
95 if(c=='\n')
96 break;
97 ch[nPos++]=c;
98 }
99 ch[nPos]=0;
100 for(;;){
101 nPos--;
102 if(nPos<0)
103 break;
104 if(ch[nPos]!='\r')
105 break;
106 ch[nPos]=0;
107 }
108 rv.ReleaseBuffer();
109 rv.FreeExtra();
110 return bRV;
111 }
112
113 inline int LoadStringList(CStringList& list,LPCTSTR section) {
114 CString n;
115 list.RemoveAll();
116 CWinApp* app = AfxGetApp();
117 ASSERT(app);
118 for(int tmp=0;;tmp++){
119 n.Format("%d",tmp);
120 CString str = app->GetProfileString(section,n,NULL);
121 if(str.IsEmpty())
122 break;
123 list.AddTail(str);
124 }
125 return tmp;
126 }
127 inline int SaveStringList(CStringList& list,LPCTSTR section) {
128 CString n;
129 CWinApp* app = AfxGetApp();
130 ASSERT(app);
131 POSITION p = list.GetHeadPosition();
132 for(int tmp=0;p;tmp++){
133 n.Format("%d",tmp);
134 app->WriteProfileString(section,n,list.GetNext(p));
135 }
136 n.Format("%d",tmp);
137 app->WriteProfileString(section,n,NULL);
138 return tmp;
139 }
140
141 inline BOOL WriteProfileString(LPCTSTR section,LPCTSTR entry,LPCTSTR str) {
142 CWinApp* app = AfxGetApp();
143 return app->WriteProfileBinary(section,entry,(LPBYTE)str,strlen(str)+1);
144 }
145 inline CString GetProfileString(LPCTSTR section,LPCTSTR entry,LPCTSTR defval) {
146 CWinApp* app = AfxGetApp();
147 LPBYTE pData;
148 UINT nCount;
149 CString rv = defval;
150 if(app->GetProfileBinary(section,entry,&pData,&nCount)){
151 rv = (LPCTSTR)pData;
152 delete pData;
153 }
154 return rv;
155 }
156
157};
158
159#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 @@
1#include "../stdafx.h"
2#include "kICMP.h"
3
4CICMP::_mechanismus CICMP::m_mechanismus = CICMP::_icmpUndetermined;
5
6BOOL CICMPDll::Initialize()
7{
8 if(m_hICMP!=INVALID_HANDLE_VALUE || m_hICMPDLL)
9 Deinitialize();
10 m_hICMPDLL = ::LoadLibraryEx("ICMP",NULL,0);
11 if(!m_hICMPDLL)
12 return FALSE;
13 *(FARPROC*)&m_icmpCF = ::GetProcAddress(m_hICMPDLL,"IcmpCreateFile");
14 *(FARPROC*)&m_icmpSE = ::GetProcAddress(m_hICMPDLL,"IcmpSendEcho");
15 *(FARPROC*)&m_icmpCH = ::GetProcAddress(m_hICMPDLL,"IcmpCloseHandle");
16 if(!(m_icmpCF && m_icmpSE && m_icmpCH)){
17 Deinitialize(); return FALSE;
18 }
19 m_hICMP = (*m_icmpCF)();
20 if(m_hICMP==INVALID_HANDLE_VALUE){
21 Deinitialize(); return FALSE;
22 }
23 TRACE0("ICMP-DLL Initialized\n");
24 return TRUE;
25}
26void CICMPDll::Deinitialize()
27{
28 if(m_hICMPDLL){
29 if(m_hICMP!=INVALID_HANDLE_VALUE && m_icmpCH)
30 (*m_icmpCH)(m_hICMP);
31 ::FreeLibrary(m_hICMPDLL); m_hICMPDLL = NULL;
32 m_icmpCF = NULL;
33 m_icmpSE = NULL;
34 m_icmpCH = NULL;
35 }
36 m_hICMP=INVALID_HANDLE_VALUE;
37 if(m_sizeOut && m_bsOut){
38 delete m_bsOut;
39 m_bsOut = NULL; m_sizeOut = 0;
40 }
41 if(m_sizeIn && m_bsIn){
42 delete m_bsIn;
43 m_bsIn = NULL; m_sizeIn = 0;
44 }
45}
46
47LONG CICMPDll::Ping(const in_addr host,const UINT packetSize,
48 const UINT timeOut,LPINT pStatus)
49{
50 if(!(m_hICMP && m_hICMPDLL && m_icmpSE)){
51 if(pStatus)
52 (*pStatus) = icmpNotInitialized;
53 return -1;
54 }
55 VERIFY(AdjustBuffers(packetSize));
56IPINFO ipi;
57 memset(&ipi,0,sizeof(ipi));
58 ipi.Ttl = 30;
59 for(UINT tmp=0;tmp<packetSize;tmp++)
60 m_bsOut[tmp]=tmp&0xFF;
61LPICMPECHO pRep = (LPICMPECHO)m_bsIn;
62 pRep->Status = 0xFFFFFFFFl;
63 if((*m_icmpSE)(m_hICMP,host.s_addr,m_bsOut,packetSize,
64 &ipi,pRep,m_sizeIn,timeOut))
65 TRACE0("ICMP-SendEcho succeeded\n");
66 else
67 TRACE0("ICMP-SendEcho failed\n");
68LONG lrv = -1;
69INT rv = ipUnknown;
70 switch(pRep->Status){
71 case IP_SUCCESS:
72 lrv = pRep->RTTime; rv = ipSuccess;
73 break;
74 case IP_BUF_TOO_SMALL: rv = ipBuffTooSmall; break;
75 case IP_DEST_NET_UNREACHABLE: rv = ipDestNetUnreachable; break;
76 case IP_DEST_HOST_UNREACHABLE: rv = ipDestHostUnreachable; break;
77 case IP_DEST_PROT_UNREACHABLE: rv = ipDestProtUnreachable; break;
78 case IP_DEST_PORT_UNREACHABLE: rv = ipDestPortUnreachable; break;
79 case IP_NO_RESOURCES: rv = ipNoResources; break;
80 case IP_BAD_OPTION: rv = ipBadOption; break;
81 case IP_HW_ERROR: rv = ipHWError; break;
82 case IP_PACKET_TOO_BIG: rv = ipPacketTooBig; break;
83 case IP_REQ_TIMED_OUT: rv = ipTimeOut; break;
84 case IP_BAD_REQ: rv = ipBadRequest; break;
85 case IP_BAD_ROUTE: rv = ipBadRoute; break;
86 case IP_TTL_EXPIRED_TRANSIT: rv = ipTTLExpiredInTransit; break;
87 case IP_TTL_EXPIRED_REASSEM: rv = ipTTLExpiredInReasm; break;
88 case IP_PARAM_PROBLEM: rv = ipParamProblem; break;
89 case IP_SOURCE_QUENCH: rv = ipSourceQuench; break;
90 case IP_OPTION_TOO_BIG: rv = ipOptionTooBig; break;
91 case IP_BAD_DESTINATION: rv = ipBadDest; break;
92 }
93 if(pStatus)
94 (*pStatus)=rv;
95 return lrv;
96}
97
98BOOL CICMPDll::AdjustBuffers(UINT packetSize)
99{
100 if(!packetSize)
101 packetSize=1;
102 if(packetSize>m_sizeOut){
103 if(m_sizeOut && m_bsOut)
104 delete m_bsOut;
105 m_bsOut = new BYTE[m_sizeOut=packetSize];
106 if(!m_bsOut)
107 return FALSE;
108 }
109UINT sin = sizeof(ICMPECHO)+SIZE_ICMP_HDR+packetSize;
110 if(sin>m_sizeIn){
111 if(m_sizeIn && m_bsIn)
112 delete m_bsIn;
113 m_bsIn = new BYTE[m_sizeIn=sin];
114 if(!m_bsIn)
115 return FALSE;
116 }
117 return TRUE;
118}
119
120
121WORD CICMPWS::m_icmpSeq = 0;
122
123BOOL CICMPWS::Initialize()
124{
125 if(m_socket!=INVALID_SOCKET)
126 Deinitialize();
127 m_socket = socket(AF_INET,SOCK_RAW,1/*ICMP*/);
128 if(m_socket==INVALID_SOCKET)
129 return FALSE;
130 TRACE0("ICMP-WS Initialized\n");
131 return TRUE;
132}
133void CICMPWS::Deinitialize()
134{
135 if(m_socket!=INVALID_SOCKET){
136 closesocket(m_socket);
137 m_socket=INVALID_SOCKET;
138 }
139 if(m_sizeOut && m_bsOut){
140 delete m_bsOut;
141 m_bsOut = NULL; m_sizeOut = 0;
142 }
143 if(m_sizeIn && m_bsIn){
144 delete m_bsIn;
145 m_bsIn = NULL; m_sizeIn = 0;
146 }
147}
148LONG CICMPWS::Ping(const in_addr host,const UINT packetSize,
149 const UINT timeOut,LPINT pStatus)
150{
151 if(m_socket==INVALID_SOCKET){
152 if(pStatus)
153 (*pStatus)=icmpNotInitialized;
154 }
155 VERIFY(AdjustBuffers(packetSize));
156icmp* pPacket = (icmp*)m_bsOut;
157 memset(pPacket,0,m_sizeOut);
158 pPacket->icmp_type = ICMP_ECHO;
159 pPacket->icmp_seq = m_icmpSeq++;
160 pPacket->icmp_id = (WORD)(::GetCurrentThreadId()&0xFFFF);
161 for(UINT tmp=0;tmp<packetSize;tmp++)
162 pPacket->icmp_data[tmp]=tmp&0xFF;
163 pPacket->icmp_cksum = cksum(pPacket,SIZE_ICMP_HDR+packetSize);
164sockaddr_in to;
165 memset(&to,0,sizeof(to));
166 to.sin_addr.s_addr = host.s_addr;
167 to.sin_family = AF_INET;
168 if(sendto(m_socket,(char*)pPacket,SIZE_ICMP_HDR+packetSize,0,
169 (SOCKADDR*)&to,sizeof(to)) != (int)(SIZE_ICMP_HDR+packetSize)){
170 TRACE1("sendto: %lu\n",WSAGetLastError());
171 if(pStatus)
172 (*pStatus)=icmpSocketError;
173 return -1;
174 }
175DWORD sentTime = ::GetTickCount();
176sockaddr_in from;
177 memset(&from,0,sizeof(from));
178 from.sin_family=AF_INET;
179 from.sin_addr.s_addr=INADDR_ANY;
180fd_set fds;
181 FD_ZERO(&fds);
182 FD_SET(m_socket,&fds);
183long lrv = -1;
184INT rv = ipTimeOut;
185 for(;;){
186 DWORD ct = ::GetTickCount();
187 if((ct-sentTime)>=timeOut){
188 TRACE0("Timeout\n");
189 break;
190 }
191 timeval tv = {
192 (timeOut-ct+sentTime)/1000,
193 (timeOut-ct+sentTime)%1000
194 };// tv_sec, tv_usec (secs,microsecs)
195 if(!select(m_socket,&fds,NULL,NULL,&tv)){
196 TRACE1("select: %d\n",WSAGetLastError());
197 break;
198 }
199 DWORD rtime = ::GetTickCount();
200 ASSERT(FD_ISSET(m_socket,&fds));
201 int fl = sizeof(from);
202 int rb = recvfrom(m_socket,(char*)m_bsIn,m_sizeIn,0,(SOCKADDR*)&from,&fl);
203 ip* pIP = (ip*)m_bsIn;
204 icmp* pICMP = (icmp*)&m_bsIn[sizeof(ip)];
205 if(pICMP->icmp_id!=pPacket->icmp_id)
206 continue;
207 if(pICMP->icmp_seq!=pPacket->icmp_seq)
208 continue;
209 if(from.sin_addr.s_addr!=host.s_addr)
210 continue;
211 if(pICMP->icmp_type==ICMP_ECHOREPLY){
212 lrv=rtime-sentTime;
213 rv=ipSuccess;
214 break;
215 }
216 rv = ipUnknown;// ***
217 break;
218 }
219 if(pStatus)
220 (*pStatus)=rv;
221 return lrv;
222}
223
224BOOL CICMPWS::AdjustBuffers(UINT packetSize)
225{
226 if(!packetSize)
227 packetSize=0;
228UINT osize = packetSize+SIZE_ICMP_HDR;
229 if(m_sizeOut<osize){
230 if(m_sizeOut && m_bsOut)
231 delete m_bsOut;
232 m_bsOut = new BYTE[m_sizeOut=osize];
233 if(!m_bsOut)
234 return FALSE;
235 }
236UINT isize = osize+sizeof(ip);
237 if(m_sizeIn<isize){
238 if(m_sizeIn && m_bsIn)
239 delete m_bsIn;
240 m_bsIn = new BYTE[m_sizeIn=isize];
241 if(!m_bsIn)
242 return FALSE;
243 }
244 return TRUE;
245}
246
247WORD CICMPWS::cksum(LPVOID data,int count)
248{
249long lSum = 0;
250WORD *pData = (WORD*)data;
251 while(count>0){
252 if(count>1){
253 lSum+=*(pData++);
254 count-=2;
255 }else{
256 lSum+=((WORD)*(BYTE*)pData)&0xFF;
257 count--;
258 }
259 }
260 lSum = (lSum&0xFFFF)+(lSum>>16);
261 lSum += (lSum>>16);
262 return (~lSum)&0xFFFF;
263}
264
265CICMP* CICMP::CreateICMP()
266{
267 if(m_mechanismus==_icmpUndetermined)
268 GuessMechanismus();
269 switch(m_mechanismus){
270 case _icmpWinsock:
271 return new CICMPWS;
272 break;
273 case _icmpDLL:
274 return new CICMPDll;
275 break;
276 }
277 return NULL;
278}
279
280void CICMP::GuessMechanismus()
281{
282 m_mechanismus=_icmpUndetermined;
283SOCKET testSocket = socket(AF_INET,SOCK_RAW,1);
284 if(testSocket!=INVALID_SOCKET){
285 closesocket(testSocket);
286 m_mechanismus=_icmpWinsock;
287 }else{
288 HINSTANCE hICMP = ::LoadLibraryEx("ICMP",NULL,0);
289 if(!hICMP)
290 return;
291 BOOL isThere = (
292 ::GetProcAddress(hICMP,"IcmpCreateFile")
293 && ::GetProcAddress(hICMP,"IcmpSendEcho")
294 && ::GetProcAddress(hICMP,"IcmpCloseHandle")
295 );
296 ::FreeLibrary(hICMP);
297 if(isThere)
298 m_mechanismus=_icmpDLL;
299 }
300} \ 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 @@
1 #ifndef__KICMP_H
2#define __KICMP_H
3
4class CICMP {
5 enum _mechanismus {
6 _icmpUndetermined = -1,
7 _icmpWinsock = 0, _icmpDLL
8 };
9static _mechanismus m_mechanismus;
10static void GuessMechanismus();
11public:
12static
13 CICMP* CreateICMP();
14
15 enum {
16 ipSuccess = 0,
17 ipBuffTooSmall, ipDestNetUnreachable, ipDestHostUnreachable,
18 ipDestProtUnreachable, ipDestPortUnreachable, ipNoResources,
19 ipBadOption, ipHWError, ipPacketTooBig, ipTimeOut, ipBadRequest,
20 ipBadRoute, ipTTLExpiredInTransit, ipTTLExpiredInReasm,
21 ipParamProblem, ipSourceQuench, ipOptionTooBig, ipBadDest,
22 ipUnknown = -1,
23 icmpNotInitialized = -2,
24 icmpSocketError = -3
25 };
26
27 virtual BOOL Initialize() = 0;
28 virtual void Deinitialize() = 0;
29
30 virtual LONG Ping(const in_addr host,const UINT packetSize=0,
31 const UINT timeOut=10000,LPINT pStatus=NULL) = 0;
32};
33
34class CICMPDll : public CICMP {
35 HANDLE(WINAPI *m_icmpCF)(VOID);
36 BOOL(WINAPI *m_icmpSE)(HANDLE,ULONG,LPVOID,WORD,
37 PIPINFO,LPVOID,DWORD,DWORD);
38 BOOL(WINAPI *m_icmpCH)(HANDLE);
39public:
40 HINSTANCE m_hICMPDLL;
41 HANDLE m_hICMP;
42 LPBYTE m_bsIn, m_bsOut;
43 UINT m_sizeIn, m_sizeOut;
44
45 CICMPDll() : m_hICMP(INVALID_HANDLE_VALUE), m_hICMPDLL(NULL),
46 m_bsIn(NULL), m_bsOut(NULL), m_sizeIn(0), m_sizeOut(0) {}
47 virtual ~CICMPDll() { Deinitialize(); }
48
49 virtual BOOL Initialize();
50 virtual void Deinitialize();
51
52 virtual LONG Ping(const in_addr host,const UINT packetSize=0,
53 const UINT timeOut=10000,LPINT pStatus=NULL);
54
55 BOOL AdjustBuffers(UINT packetSize=0);
56};
57
58class CICMPWS : public CICMP {
59static
60 WORD m_icmpSeq;
61public:
62 SOCKET m_socket;
63 LPBYTE m_bsIn, m_bsOut;
64 UINT m_sizeIn, m_sizeOut;
65
66 CICMPWS() : m_socket(INVALID_SOCKET), m_bsIn(NULL), m_bsOut(NULL),
67 m_sizeIn(0), m_sizeOut(0) {}
68 virtual ~CICMPWS() { Deinitialize(); }
69
70 virtual BOOL Initialize();
71 virtual void Deinitialize();
72
73 virtual LONG Ping(const in_addr host,const UINT packetSize=0,
74 const UINT timeOut=10000,LPINT pStatus=NULL);
75
76 BOOL AdjustBuffers(UINT packetSize=0);
77 WORD cksum(LPVOID data,int count);
78};
79
80#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 @@
1<?xml version="1.0"?>
2<xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 >
5 <xsl:output
6 method="text"
7 encoding="us-ascii"/>
8 <xsl:strip-space elements="*"/>
9
10 <xsl:template match="winhelp">
11 <xsl:text>{\rtf1\ansi</xsl:text>
12 <xsl:text>&#xA;@{\footnote</xsl:text>
13 <xsl:text>&#xA;THIS FILE WAS AUTOMATICALLY GENERATED FROM XML DOCUMENT.</xsl:text>
14 <xsl:text>&#xA;DO NOT MODIFY THIS FILE DIRECTLY. EDIT XML DOCUMENT INSTEAD</xsl:text>
15 <xsl:text>&#xA;}&#xA;</xsl:text>
16 <xsl:call-template name="fonttbl"/>
17 <xsl:call-template name="colortbl"/>
18 <xsl:apply-templates/>
19 <xsl:text>}</xsl:text>
20 </xsl:template>
21
22 <xsl:template match="topic">
23 <xsl:text>&#xA;\pard\plain</xsl:text>
24 <xsl:if test="descendant::*[ (@scroll='no') and
25 count(preceding-sibling::*[not(@scroll='no') and (name()!='a' and @name)])=0] ">
26 <xsl:text>\keepn</xsl:text>
27 </xsl:if>
28 <xsl:if test="@id">
29 <xsl:text>&#xA;#{\footnote </xsl:text>
30 <xsl:value-of select="@id"/>
31 <xsl:text>}</xsl:text>
32 </xsl:if>
33 <xsl:if test="@title">
34 <xsl:text>&#xA;${\footnote </xsl:text>
35 <xsl:value-of select="@title"/>
36 <xsl:text>}</xsl:text>
37 </xsl:if>
38 <xsl:if test="@keywords">
39 <xsl:text>&#xA;K{\footnote </xsl:text>
40 <xsl:value-of select="@keywords"/>
41 <xsl:text>}</xsl:text>
42 </xsl:if>
43 <xsl:apply-templates/>
44 <xsl:text>&#xA;\page&#xA;</xsl:text>
45 </xsl:template>
46
47 <xsl:template match="a[@name]">
48 <xsl:text>{#{\footnote </xsl:text>
49 <xsl:value-of select="@name"/>
50 <xsl:text>}}</xsl:text>
51 </xsl:template>
52 <xsl:template match="a[@href]">
53 <xsl:call-template name="hyperref">
54 <xsl:with-param name="href" select="@href"/>
55 <xsl:with-param name="inset"><xsl:apply-templates/></xsl:with-param>
56 </xsl:call-template>
57 </xsl:template>
58 <xsl:template name="hyperref">
59 <xsl:param name="href"/>
60 <xsl:param name="inset"/>
61 <xsl:choose>
62 <xsl:when test="starts-with($href,'http:') or starts-with($href,'mailto:') or
63 starts-with($href,'ftp:')">
64 <xsl:text>{\uldb </xsl:text>
65 <xsl:value-of select="$inset"/>
66 <xsl:text>}{\v %!ExecFile("</xsl:text>
67 <xsl:value-of select="$href"/>
68 <xsl:text>")}</xsl:text>
69 </xsl:when>
70 <xsl:when test="starts-with($href,'#')">
71 <xsl:text>{\uldb </xsl:text>
72 <xsl:value-of select="$inset"/>
73 <xsl:text>}{\v </xsl:text>
74 <xsl:value-of select="substring($href,2)"/>
75 <xsl:text>}</xsl:text>
76 </xsl:when>
77 <xsl:otherwise>
78 <xsl:message>Warining: Unqualified hyper-reference. Using as help-internal</xsl:message>
79 <xsl:text>{\uldb </xsl:text>
80 <xsl:value-of select="$inset"/>
81 <xsl:text>}{\v </xsl:text>
82 <xsl:value-of select="$href"/>
83 <xsl:text>}</xsl:text>
84 </xsl:otherwise>
85 </xsl:choose>
86 </xsl:template>
87
88 <xsl:template match="heading">
89 <xsl:text>&#xA;</xsl:text>
90 <xsl:if test="@scroll!='no'">
91 <xsl:text>\pard </xsl:text>
92 </xsl:if>
93 <xsl:text>{ \f1\fs18\b\sb120 </xsl:text>
94 <xsl:apply-templates/>
95 <xsl:text>}</xsl:text>
96 </xsl:template>
97
98 <xsl:template match="p">
99 <xsl:text>&#xA;\par\sa120\sb120\qj</xsl:text>
100 <xsl:if test="@scroll!='no'">
101 <xsl:text>\pard</xsl:text>
102 </xsl:if>
103 <xsl:text> \f1\fs18\sb120 </xsl:text>
104 <xsl:apply-templates/>
105 </xsl:template>
106
107 <xsl:template match="note">
108 <xsl:text>&#xA;\par\sa120\sb120\qj\f1\fs16 </xsl:text>
109 <xsl:apply-templates/>
110 </xsl:template>
111
112 <xsl:template match="dedication">
113 <xsl:text>&#xA;\par\sa120\sb120\qr\f1\fs16 </xsl:text>
114 <xsl:apply-templates/>
115 </xsl:template>
116
117 <xsl:template match="image">
118 <xsl:text>\{bmct </xsl:text>
119 <xsl:value-of select="@source"/>
120 <xsl:text>\}</xsl:text>
121 </xsl:template>
122
123 <xsl:template match="newsfor">
124 <xsl:text>&#xA;\par\pard\plain\f1\fs24\qc\cf2\b </xsl:text>
125 <xsl:value-of select="@version"/>
126 <xsl:text> - </xsl:text>
127 <xsl:value-of select="@date"/>
128 <xsl:apply-templates/>
129 </xsl:template>
130 <xsl:template match="ni">
131 <xsl:text>&#xA;\par\pard\plain\fi0\li0\f1\fs18 \bullet </xsl:text>
132 <xsl:apply-templates/>
133 </xsl:template>
134
135 <xsl:template match="b">
136 <xsl:text>{\b </xsl:text>
137 <xsl:apply-templates/>
138 <xsl:text>}</xsl:text>
139 </xsl:template>
140 <xsl:template match="i">
141 <xsl:text>{\i </xsl:text>
142 <xsl:apply-templates/>
143 <xsl:text>}</xsl:text>
144 </xsl:template>
145 <xsl:template match="u">
146 <xsl:text>{\ul </xsl:text>
147 <xsl:apply-templates/>
148 <xsl:text>}</xsl:text>
149 </xsl:template>
150 <xsl:template match="strike">
151 <xsl:text>{\strike </xsl:text>
152 <xsl:apply-templates/>
153 <xsl:text>}</xsl:text>
154 </xsl:template>
155
156 <xsl:template match="kin">
157 <xsl:choose>
158 <xsl:when test="@href">
159 <xsl:call-template name="hyperref">
160 <xsl:with-param name="href" select="@href"/>
161 <xsl:with-param name="inset"><xsl:text>{\b </xsl:text><xsl:apply-templates/><xsl:text>}</xsl:text></xsl:with-param>
162 </xsl:call-template>
163 </xsl:when>
164 <xsl:otherwise>
165 <xsl:text>{\b </xsl:text>
166 <xsl:apply-templates/>
167 <xsl:text>}</xsl:text>
168 </xsl:otherwise>
169 </xsl:choose>
170 </xsl:template>
171 <xsl:template match="product">
172 <xsl:choose>
173 <xsl:when test="@href">
174 <xsl:call-template name="hyperref">
175 <xsl:with-param name="href" select="@href"/>
176 <xsl:with-param name="inset"><xsl:text>{\b\cf6 </xsl:text><xsl:apply-templates/><xsl:text>}</xsl:text></xsl:with-param>
177 </xsl:call-template>
178 </xsl:when>
179 <xsl:otherwise>
180 <xsl:text>{\b\cf6 </xsl:text>
181 <xsl:apply-templates/>
182 <xsl:text>}</xsl:text>
183 </xsl:otherwise>
184 </xsl:choose>
185 </xsl:template>
186 <xsl:template match="term">
187 <xsl:text>{\i </xsl:text>
188 <xsl:apply-templates/>
189 <xsl:text>}</xsl:text>
190 </xsl:template>
191
192 <xsl:template match="rfc">
193 <xsl:call-template name="hyperref">
194 <xsl:with-param name="href" select="concat('http://www.rfc-editor.org/rfc/rfc',@num,'.txt')"/>
195 <xsl:with-param name="inset" select="concat('{\b RFC',@num,'}')"/>
196 </xsl:call-template>
197 </xsl:template>
198
199 <xsl:template match="license">
200 <xsl:text>&#xA;{</xsl:text>
201 <xsl:text>&#xA;\par\pard\plain\sb360\sa120 \f1\fs16 Copyright (c) </xsl:text>
202 <xsl:value-of select="@years"/>
203 <xsl:text> {\uldb\cf0 Klever Group (http://www.klever.net/)}{\v %!ExecFile("http://www.klever.net/")}</xsl:text>
204 <xsl:text>&#xA;\par\qj\sb120\sa120</xsl:text>
205 <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>
206 <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>
207 <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>
208 <xsl:text>&#xA;}</xsl:text>
209 </xsl:template>
210 <xsl:template match="credits">
211 <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>
212 <xsl:text>&#xA;\par \sa0\sb0 Fan mail send to {\i\uldb gefilte@klever.net}{\v %!ExecFile("mailto:gefilte@klever.net")}</xsl:text>
213 </xsl:template>
214
215 <xsl:template match="ul">
216 <xsl:text>\pard</xsl:text>
217 <xsl:apply-templates/>
218 <xsl:text>\pard</xsl:text>
219 </xsl:template>
220 <xsl:template match="li">
221 <!-- TODO: could be done better, but you never know with winhelp.. -->
222 <xsl:variable name="li" select=" count(ancestor::ul) "/>
223 <xsl:text>&#xA;\par \fi0\li</xsl:text><xsl:value-of
224 select="0"/><xsl:text> \bullet </xsl:text>
225 <xsl:apply-templates/>
226 </xsl:template>
227
228 <xsl:template match="topic/text()">
229 <!-- maybe only omit spaces? -->
230 </xsl:template>
231 <xsl:template match="ul/text()">
232 </xsl:template>
233
234 <xsl:template name="colortbl">
235 <xsl:text>{\colortbl;
236 \red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;
237 \red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;
238 \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;
239 \red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
240 </xsl:text>
241 </xsl:template>
242 <xsl:template name="fonttbl">
243 <xsl:text>{\fonttbl</xsl:text>
244 <xsl:text>{\f0\froman Times New Roman;}</xsl:text>
245 <xsl:text>{\f1\fswiss Arial;}</xsl:text>
246 <xsl:text>{\f3\froman Symbol;}</xsl:text>
247 <xsl:text>}</xsl:text>
248 </xsl:template>
249
250</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 @@
1/*------------------------------------------------------------------
2* Filename: MS_ICMP.H
3*
4* Description: Prototypes of Microsoft's ICMP.DLL functions for
5* access to Internet Control Message Protocol (their stacks do
6* not support the standard Berkeley Sockets raw socket API).
7* Use this to do "ping" or "traceroute," although beware that
8* Microsoft discourages its use.
9*/
10
11
12/* Note 2: For the most part, you can refer to RFC 791 for detials on
13* how to fill in values for the IP option information structure. */
14typedef struct ip_option_information {
15 u_char Ttl; /* Time To Live (used for traceroute) */
16 u_char Tos; /* Type Of Service (usually 0) */
17 u_char Flags; /* IP header flags (usually 0) */
18 u_char OptionsSize; /* Size of options data (usually 0, max 40) */
19 u_char FAR *OptionsData;/* Options data buffer */
20 }IPINFO, *PIPINFO, FAR *LPIPINFO;
21
22/* Note 1: The Reply Buffer will have an array of ICMP_ECHO_REPLY
23* structures, followed by options and the data in ICMP echo reply
24* datagram received. You must have room for at least one ICMP
25* echo reply structure, plus 8 bytes for an ICMP header. */
26typedef struct icmp_echo_reply {
27 u_long Address; /* source address */
28 u_long Status; /* IP status value (see below) */
29 u_long RTTime; /* Round Trip Time in milliseconds */
30 u_short DataSize; /* reply data size */
31 u_short Reserved; /* */
32 void FAR *Data; /* reply data buffer */
33 typedef struct ip_option_information Options; /* reply options */
34 }ICMPECHO, *PICMPECHO, FAR *LPICMPECHO;
35
36#define IP_STATUS_BASE 11000
37#define IP_SUCCESS 0
38#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
39#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
40#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
41#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
42#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
43#define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
44#define IP_BAD_OPTION (IP_STATUS_BASE + 7)
45#define IP_HW_ERROR (IP_STATUS_BASE + 8)
46#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
47#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
48#define IP_BAD_REQ (IP_STATUS_BASE + 11)
49#define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
50#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
51#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
52#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
53#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
54#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
55#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
56#define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
57#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
58#define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
59#define IP_UNLOAD (IP_STATUS_BASE + 22)
60#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
61#define MAX_IP_STATUS IP_GENERAL_FAILURE
62#define IP_PENDING (IP_STATUS_BASE + 255)
63
64
65HANDLE WINAPI PASCAL IcmpCreateFile(VOID); /* INVALID_HANDLE_VALUE on error */
66BOOL WINAPI PASCAL IcmpCloseHandle(HANDLE IcmpHandle); /* FALSE on error */
67DWORD WINAPI PASCAL IcmpSendEcho(
68 HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
69 u_long DestAddress, /* destination IP address (in network order) */
70 LPVOID RequestData, /* pointer to buffer to send */
71 WORD RequestSize, /* length of data in buffer */
72 LPIPINFO RequestOptns, /* see Note 2 below */
73 LPVOID ReplyBuffer, /* see Note 1 below */
74 DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
75 DWORD Timeout /* time in milliseconds to wait for reply */
76);
77
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/status.cpp b/status.cpp
new file mode 100644
index 0000000..3338590
--- a/dev/null
+++ b/status.cpp
@@ -0,0 +1,30 @@
1
2 enum _STSB{
3 stsbSend = 1,
4 stsbIs = 0
5};
6
7BOOL statusOnDo()
8{
9 TRACE0("DO STATUS\n");
10 return TRUE;
11}
12BOOL statusOnWill()
13{
14 TRACE0("WILL STATUS\n");
15 return TRUE;
16}
17BOOL statusOnSB(LPBYTE data,UINT size)
18{
19 if(!size)
20 return FALSE;
21 switch(data[0]){
22 case stsbSend:
23 TRACE0("SB STATUS SEND\n");
24 break;
25 case stsbIs:
26 TRACE0("SB STATUS IS\n");
27 break;
28 }
29 return TRUE;
30} \ No newline at end of file
diff --git a/terminal.cpp b/terminal.cpp
new file mode 100644
index 0000000..f60ce8b
--- a/dev/null
+++ b/terminal.cpp
@@ -0,0 +1,147 @@
1extern int TTTermType;
2class CTTY;
3 struct_tType {
4 LPCTSTR m_Name;
5 CTTY* m_Termcap;
6};
7extern _tType TTypes[];
8
9BOOL TerminalUpdateTitle();
10
11#include "TTY.cpp"
12#include "VT100.cpp"
13
14 enum _TTSB{
15 ttsbSend = 1,
16 ttsbIs = 0
17};
18
19_tType TTypes[] = {
20 {"VT102",&TT_VT100},
21 {"DEC-VT102",&TT_VT100},
22 {"VT100",&TT_VT100},
23 {"DEC-VT100",&TT_VT100},
24 {"ANSI",&TT_VT100},
25 {"TTY",&TT_TTY},
26 {"UNKNOWN",&TT_TTY},
27 {"DUMB",&TT_TTY}
28};
29 intTType = -1;
30CTTY* TTTerm = NULL;
31int TTTermType = -1;
32
33BOOL TerminalPullType(LPCTSTR ttype,LPCTSTR newName=NULL)
34{
35 for(int tmp=0;tmp<(sizeof(TTypes)/sizeof(*TTypes));tmp++){
36 if(!stricmp(ttype,TTypes[tmp].m_Name)){
37 if(tmp){
38 _tType t;
39 memmove(&t,&TTypes[tmp],sizeof(t));
40 memmove(&TTypes[1],&TTypes[0],sizeof(*TTypes)*tmp);
41 memmove(&TTypes[0],&t,sizeof(TTypes[0]));
42 }
43 if(newName)
44 TTypes[0].m_Name=newName;
45 return TRUE;
46 }
47 }
48 return FALSE;
49}
50BOOL TerminalPrintTypes()
51{
52 for(int tmp=0;tmp<(sizeof(TTypes)/sizeof(*TTypes));tmp++)
53 printf(" %s",TTypes[tmp].m_Name);
54 return TRUE;
55}
56
57BOOL TerminalUpdateTitle()
58{
59CHAR consoleTitle[1024];
60 sprintf(consoleTitle,DAMN_KIN_NAME " %s:%s - %s",remoteHost,remoteProt,TTTerm->GetTitle());
61 return SetConsoleTitle(consoleTitle);
62}
63
64BOOL SelectTermType(int tt)
65{
66 if(tt<0)
67 tt=0;
68 if(tt>=(sizeof(TTypes)/sizeof(*TTypes)))
69 tt = sizeof(TTypes)/sizeof(*TTypes)-1;
70 TTTerm = TTypes[tt].m_Termcap;
71 TTTermType=tt;
72 VERIFY(TTTerm->Init());
73 return TerminalUpdateTitle();
74}
75BOOL TerminalOut(BYTE c)
76{
77 ASSERT(TTTerm);
78 return TTTerm->Output(c);
79}
80BOOL TerminalIn(KEY_EVENT_RECORD k)
81{
82 ASSERT(TTTerm);
83 if(k.uChar.AsciiChar){// Maybe fall for V-Processing if ENHANCED_KEY
84 // Workaround for ENTER's \r/\n dilemma.. ***********
85 // Maybe should be moved to termtype-dependant code
86 CHAR c = k.uChar.AsciiChar;
87 if(k.wVirtualKeyCode==VK_RETURN){
88 if(c=='\r')
89 return TTTerm->Input('\r') && TTTerm->Input('\n');
90 else if(c=='\n')
91 return TTTerm->Input('\n');
92 }
93 return TTTerm->Input(c);
94 }else
95 return TTTerm->VInput(k.wVirtualKeyCode,k.dwControlKeyState);
96}
97BOOL TerminalIn(LPCTSTR str)
98{
99 ASSERT(TTTerm);
100 while(*str)
101 TTTerm->Input(*(str++));
102 return TRUE;
103}
104BOOL TerminalPreO()
105{
106 ASSERT(TTTerm);
107 return TTTerm->PreOutput();
108}
109BOOL TerminalPostO()
110{
111 ASSERT(TTTerm);
112 return TTTerm->PostOutput();
113}
114
115BOOL terminaltypeOnInit()
116{
117 VERIFY(SetConsoleMode(hConsoleInput,0));
118 TType = -1;
119 return SelectTermType(0);
120}
121BOOL terminaltypeOnDo()
122{
123 TRACE0("DO TERMINAL-TYPE\n");
124 return TRUE;
125}
126BOOL terminaltypeOnSB(LPBYTE data,UINT size)
127{
128 if(!size)
129 return FALSE;
130 if(data[0]!=ttsbSend)
131 return FALSE;
132 TRACE0("SB TERMINAL-TYPE SEND\n");
133 TType++;
134 if(TType>(sizeof(TTypes)/sizeof(*TTypes)))
135 TType=0;
136int tt = TType;
137 if(tt>=(sizeof(TTypes)/sizeof(*TTypes)))
138 tt = sizeof(TTypes)/sizeof(*TTypes)-1;
139 VERIFY(SelectTermType(tt));
140int ds = strlen(TTypes[tt].m_Name)+1;
141LPBYTE lpb = new BYTE[ds];
142 lpb[0] = ttsbIs;
143 memmove(&lpb[1],TTypes[tt].m_Name,ds-1);
144 VERIFY(SubNegotiate(toTerminalType,lpb,ds));
145 delete lpb;
146 return TRUE;
147}