1 |
#include "teraterm.h" |
2 |
#include "tttypes.h" |
3 |
#include "ttplugin.h" |
4 |
#include "ttlib.h" |
5 |
#include "tt_res.h" |
6 |
#include "resource.h" |
7 |
|
8 |
#include "compat_w95.h" |
9 |
|
10 |
#define ORDER 4000 |
11 |
|
12 |
#define MINIMUM_INTERVAL 10 |
13 |
#define DEFAULT_INTERVAL 300 |
14 |
|
15 |
#define IdRecurringTimer 3001 |
16 |
|
17 |
#define ID_MENU_SETUP 55500 |
18 |
|
19 |
#define SECTION "TTXRecurringCommand" |
20 |
|
21 |
static HANDLE hInst; |
22 |
|
23 |
typedef struct { |
24 |
PTTSet ts; |
25 |
PComVar cv; |
26 |
Tsend origPsend; |
27 |
TWriteFile origPWriteFile; |
28 |
PReadIniFile origReadIniFile; |
29 |
PWriteIniFile origWriteIniFile; |
30 |
HMENU SetupMenu; |
31 |
int interval; |
32 |
BOOL enable; |
33 |
int cmdLen; |
34 |
char command[50]; |
35 |
char orgCommand[50]; |
36 |
} TInstVar; |
37 |
|
38 |
typedef TInstVar FAR * PTInstVar; |
39 |
PTInstVar pvar; |
40 |
static TInstVar InstVar; |
41 |
|
42 |
#define GetFileMenu(menu) GetSubMenuByChildID(menu, ID_FILE_NEWCONNECTION) |
43 |
#define GetEditMenu(menu) GetSubMenuByChildID(menu, ID_EDIT_COPY2) |
44 |
#define GetSetupMenu(menu) GetSubMenuByChildID(menu, ID_SETUP_TERMINAL) |
45 |
#define GetControlMenu(menu) GetSubMenuByChildID(menu, ID_CONTROL_RESETTERMINAL) |
46 |
#define GetHelpMenu(menu) GetSubMenuByChildID(menu, ID_HELP_ABOUT) |
47 |
|
48 |
HMENU GetSubMenuByChildID(HMENU menu, UINT id) { |
49 |
int i, j, items, subitems, cur_id; |
50 |
HMENU m; |
51 |
|
52 |
items = GetMenuItemCount(menu); |
53 |
|
54 |
for (i=0; i<items; i++) { |
55 |
if (m = GetSubMenu(menu, i)) { |
56 |
subitems = GetMenuItemCount(m); |
57 |
for (j=0; j<subitems; j++) { |
58 |
cur_id = GetMenuItemID(m, j); |
59 |
if (cur_id == id) { |
60 |
return m; |
61 |
} |
62 |
} |
63 |
} |
64 |
} |
65 |
return NULL; |
66 |
} |
67 |
|
68 |
WORD GetOnOff(PCHAR Sect, PCHAR Key, PCHAR FName, BOOL Default) |
69 |
{ |
70 |
char Temp[4]; |
71 |
GetPrivateProfileString(Sect, Key, "", Temp, sizeof(Temp), FName); |
72 |
if (Default) { |
73 |
if (_stricmp(Temp, "off") == 0) |
74 |
return 0; |
75 |
else |
76 |
return 1; |
77 |
} |
78 |
else { |
79 |
if (_stricmp(Temp, "on") == 0) |
80 |
return 1; |
81 |
else |
82 |
return 0; |
83 |
} |
84 |
} |
85 |
|
86 |
// |
87 |
// \n, \t�����W�J�����B |
88 |
// common/ttlib.c:RestoreNewLine()���x�[�X�B |
89 |
// |
90 |
void RestoreNewLine(PCHAR Text) |
91 |
{ |
92 |
unsigned int i, j=0; |
93 |
size_t size; |
94 |
char *buf; |
95 |
|
96 |
size = strlen(Text); |
97 |
buf = malloc(size+1); |
98 |
|
99 |
memset(buf, 0, size+1); |
100 |
for (i=0; i<size; i++) { |
101 |
if (Text[i] == '\\' && i<size ) { |
102 |
switch (Text[i+1]) { |
103 |
case '\\': |
104 |
buf[j] = '\\'; |
105 |
i++; |
106 |
break; |
107 |
case 'n': |
108 |
buf[j] = '\n'; |
109 |
i++; |
110 |
break; |
111 |
case 't': |
112 |
buf[j] = '\t'; |
113 |
i++; |
114 |
break; |
115 |
case '0': |
116 |
buf[j] = '\0'; |
117 |
i++; |
118 |
break; |
119 |
default: |
120 |
buf[j] = '\\'; |
121 |
} |
122 |
} |
123 |
else { |
124 |
buf[j] = Text[i]; |
125 |
} |
126 |
j++; |
127 |
} |
128 |
/* use memcpy to copy with '\0' */ |
129 |
memcpy(Text, buf, size); |
130 |
|
131 |
free(buf); |
132 |
} |
133 |
|
134 |
// |
135 |
// �o���o�b�t�@������������������ |
136 |
// ttpcmn/ttcmn.c:CommTextOut()���x�[�X |
137 |
// |
138 |
void CommOut(char *str, int len) { |
139 |
int outlen, c; |
140 |
char *p; |
141 |
|
142 |
if (len > OutBuffSize - pvar->cv->OutBuffCount) |
143 |
outlen = OutBuffSize - pvar->cv->OutBuffCount; |
144 |
else |
145 |
outlen = len; |
146 |
|
147 |
if (pvar->cv->OutPtr > 0) { |
148 |
memmove(pvar->cv->OutBuff, &(pvar->cv->OutBuff[pvar->cv->OutPtr]), pvar->cv->OutBuffCount); |
149 |
pvar->cv->OutPtr = 0; |
150 |
} |
151 |
|
152 |
c = pvar->cv->OutBuffCount; |
153 |
for (p=str; outlen>0; p++, outlen--) { |
154 |
switch (*p) { |
155 |
case 0x0d: |
156 |
switch (pvar->cv->CRSend) { |
157 |
case IdCR: |
158 |
pvar->cv->OutBuff[c++] = 0x0d; |
159 |
if (c < OutBuffSize && pvar->cv->TelFlag && ! pvar->cv->TelBinSend) { |
160 |
pvar->cv->OutBuff[c++] = 0; |
161 |
} |
162 |
break; |
163 |
case IdLF: |
164 |
pvar->cv->OutBuff[c++] = 0x0a; |
165 |
break; |
166 |
case IdCRLF: |
167 |
pvar->cv->OutBuff[c++] = 0x0d; |
168 |
if (c < OutBuffSize) { |
169 |
pvar->cv->OutBuff[c++] = 0x0a; |
170 |
} |
171 |
break; |
172 |
} |
173 |
if (c + outlen > OutBuffSize) { |
174 |
outlen--; |
175 |
} |
176 |
break; |
177 |
case 0xff: |
178 |
if (pvar->cv->TelFlag) { |
179 |
if (c < OutBuffSize - 1) { |
180 |
pvar->cv->OutBuff[c++] = 0xff; |
181 |
pvar->cv->OutBuff[c++] = 0xff; |
182 |
} |
183 |
} |
184 |
else { |
185 |
pvar->cv->OutBuff[c++] = 0xff; |
186 |
} |
187 |
if (c + outlen > OutBuffSize) { |
188 |
outlen--; |
189 |
} |
190 |
break; |
191 |
default: |
192 |
pvar->cv->OutBuff[c++] = *p; |
193 |
} |
194 |
} |
195 |
|
196 |
pvar->cv->OutBuffCount = c; |
197 |
} |
198 |
|
199 |
// |
200 |
// �^�C�}���^�C���A�E�g���������R�[���o�b�N���� |
201 |
// �L���������������������A�o���o�b�t�@���R�}���h���������� |
202 |
// |
203 |
void CALLBACK RecurringTimerProc(HWND hwnd, UINT msg, UINT_PTR ev, DWORD now) { |
204 |
if (pvar->enable && pvar->cmdLen > 0 && pvar->cv->Ready && pvar->cv->OutBuffCount == 0) { |
205 |
CommOut(pvar->command, pvar->cmdLen); |
206 |
} |
207 |
// SendMessage(hwnd, WM_IDLE, 0, 0); |
208 |
return; |
209 |
} |
210 |
|
211 |
// |
212 |
// TTXInit -- �N�������� |
213 |
// |
214 |
static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv) { |
215 |
pvar->ts = ts; |
216 |
pvar->cv = cv; |
217 |
pvar->origPsend = NULL; |
218 |
pvar->origPWriteFile = NULL; |
219 |
pvar->origReadIniFile = NULL; |
220 |
pvar->origWriteIniFile = NULL; |
221 |
pvar->interval = DEFAULT_INTERVAL; |
222 |
} |
223 |
|
224 |
// |
225 |
// TTXSend, TTXWriteFile -- �L�[�������� |
226 |
// �L�[���������������A�^�C�}���������� |
227 |
// |
228 |
static int PASCAL FAR TTXsend(SOCKET s, const char FAR *buf, int len, int flags) { |
229 |
if (pvar->enable && len > 0) { |
230 |
SetTimer(pvar->cv->HWin, IdRecurringTimer, pvar->interval * 1000, RecurringTimerProc); |
231 |
} |
232 |
return pvar->origPsend(s, buf, len, flags); |
233 |
} |
234 |
|
235 |
static BOOL PASCAL FAR TTXWriteFile(HANDLE fh, LPCVOID buff, DWORD len, LPDWORD wbytes, LPOVERLAPPED wol) { |
236 |
if (pvar->enable && len > 0) { |
237 |
SetTimer(pvar->cv->HWin, IdRecurringTimer, pvar->interval * 1000, RecurringTimerProc); |
238 |
} |
239 |
return pvar->origPWriteFile(fh, buff, len, wbytes, wol); |
240 |
} |
241 |
|
242 |
// |
243 |
// TTXOpenTCP, TTXOpenFile -- �Z�b�V�����J�n���� |
244 |
// Psend, WriteFile���t�b�N���A�L���������^�C�}���Z�b�g�����B |
245 |
// |
246 |
static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks) { |
247 |
pvar->origPsend = *hooks->Psend; |
248 |
*hooks->Psend = TTXsend; |
249 |
|
250 |
if (pvar->enable && pvar->cmdLen > 0) { |
251 |
SetTimer(pvar->cv->HWin, IdRecurringTimer, pvar->interval * 1000, RecurringTimerProc); |
252 |
} |
253 |
} |
254 |
|
255 |
static void PASCAL FAR TTXOpenFile(TTXFileHooks FAR * hooks) { |
256 |
pvar->origPWriteFile = *hooks->PWriteFile; |
257 |
*hooks->PWriteFile = TTXWriteFile; |
258 |
|
259 |
if (pvar->enable && pvar->cmdLen > 0) { |
260 |
SetTimer(pvar->cv->HWin, IdRecurringTimer, pvar->interval * 1000, RecurringTimerProc); |
261 |
} |
262 |
} |
263 |
|
264 |
// |
265 |
// TTXCloseTCP, TTXCloseFile -- �Z�b�V�����I�������� |
266 |
// Psend, WriteFile���t�b�N���������A�^�C�}���~�����B |
267 |
// |
268 |
static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks) { |
269 |
if (pvar->origPsend) { |
270 |
*hooks->Psend = pvar->origPsend; |
271 |
} |
272 |
KillTimer(pvar->cv->HWin, IdRecurringTimer); |
273 |
} |
274 |
|
275 |
static void PASCAL FAR TTXCloseFile(TTXFileHooks FAR * hooks) { |
276 |
if (pvar->origPWriteFile) { |
277 |
*hooks->PWriteFile = pvar->origPWriteFile; |
278 |
} |
279 |
KillTimer(pvar->cv->HWin, IdRecurringTimer); |
280 |
} |
281 |
|
282 |
// |
283 |
// TTXReadIniFile, TTXWriteIniFile -- �����t�@�C������������ |
284 |
// |
285 |
static void PASCAL FAR TTXReadIniFile(PCHAR fn, PTTSet ts) { |
286 |
pvar->origReadIniFile(fn, ts); |
287 |
|
288 |
GetPrivateProfileString(SECTION, "Command", "", pvar->orgCommand, sizeof(pvar->orgCommand), fn); |
289 |
strncpy_s(pvar->command, sizeof(pvar->command), pvar->orgCommand, _TRUNCATE); |
290 |
RestoreNewLine(pvar->command); |
291 |
pvar->cmdLen = (int)strlen(pvar->command); |
292 |
|
293 |
pvar->interval = GetPrivateProfileInt(SECTION, "Interval", DEFAULT_INTERVAL, fn); |
294 |
if (pvar->interval < MINIMUM_INTERVAL) { |
295 |
pvar->interval = MINIMUM_INTERVAL; |
296 |
} |
297 |
|
298 |
pvar->enable = GetOnOff(SECTION, "Enable", fn, FALSE); |
299 |
|
300 |
return; |
301 |
} |
302 |
|
303 |
static void PASCAL FAR TTXWriteIniFile(PCHAR fn, PTTSet ts) { |
304 |
char buff[20]; |
305 |
|
306 |
pvar->origWriteIniFile(fn, ts); |
307 |
|
308 |
WritePrivateProfileString(SECTION, "Enable", pvar->enable?"On":"Off", fn); |
309 |
|
310 |
WritePrivateProfileString(SECTION, "Command", pvar->orgCommand, fn); |
311 |
|
312 |
_snprintf_s(buff, sizeof(buff), _TRUNCATE, "%d", pvar->interval); |
313 |
WritePrivateProfileString(SECTION, "Interval", buff, fn); |
314 |
|
315 |
return; |
316 |
} |
317 |
|
318 |
static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks) { |
319 |
pvar->origReadIniFile = *hooks->ReadIniFile; |
320 |
*hooks->ReadIniFile = TTXReadIniFile; |
321 |
|
322 |
pvar->origWriteIniFile = *hooks->WriteIniFile; |
323 |
*hooks->WriteIniFile = TTXWriteIniFile; |
324 |
} |
325 |
|
326 |
// |
327 |
// ���j���[���� |
328 |
// �R���g���[�����j���[��RecurringCommand�������B |
329 |
// |
330 |
static void PASCAL FAR TTXModifyMenu(HMENU menu) { |
331 |
UINT flag = MF_BYCOMMAND | MF_STRING | MF_ENABLED; |
332 |
|
333 |
pvar->SetupMenu = GetSetupMenu(menu); |
334 |
|
335 |
InsertMenu(pvar->SetupMenu, ID_SETUP_ADDITIONALSETTINGS, flag, ID_MENU_SETUP, "Rec&urring command"); |
336 |
} |
337 |
|
338 |
// |
339 |
// RecurringCommand�����_�C�A���O���R�[���o�b�N�����B |
340 |
// |
341 |
static LRESULT CALLBACK RecurringCommandSetting(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) { |
342 |
switch (msg) { |
343 |
case WM_INITDIALOG: |
344 |
SendMessage(GetDlgItem(dlg, IDC_ENABLE), BM_SETCHECK, |
345 |
pvar->enable?BST_CHECKED:BST_UNCHECKED, 0); |
346 |
SetDlgItemInt(dlg, IDC_INTERVAL, pvar->interval, FALSE); |
347 |
SetDlgItemText(dlg, IDC_COMMAND, pvar->orgCommand); |
348 |
|
349 |
return TRUE; |
350 |
case WM_COMMAND: |
351 |
switch (LOWORD(wParam)) { |
352 |
case IDOK: |
353 |
pvar->enable = IsDlgButtonChecked(dlg, IDC_ENABLE) == BST_CHECKED; |
354 |
|
355 |
pvar->interval = GetDlgItemInt(dlg, IDC_INTERVAL, NULL, FALSE); |
356 |
if (pvar->interval < MINIMUM_INTERVAL) { |
357 |
pvar->interval = MINIMUM_INTERVAL; |
358 |
} |
359 |
|
360 |
GetDlgItemText(dlg, IDC_COMMAND, pvar->orgCommand, sizeof(pvar->orgCommand)); |
361 |
strncpy_s(pvar->command, sizeof(pvar->command), pvar->orgCommand, _TRUNCATE); |
362 |
RestoreNewLine(pvar->command); |
363 |
pvar->cmdLen = (int)strlen(pvar->command); |
364 |
|
365 |
if (pvar->cv->Ready) { |
366 |
if (pvar->enable) { |
367 |
SetTimer(pvar->cv->HWin, IdRecurringTimer, |
368 |
pvar->interval * 1000, RecurringTimerProc); |
369 |
} |
370 |
else { |
371 |
KillTimer(pvar->cv->HWin, IdRecurringTimer); |
372 |
} |
373 |
} |
374 |
|
375 |
EndDialog(dlg, IDOK); |
376 |
return TRUE; |
377 |
|
378 |
case IDCANCEL: |
379 |
EndDialog(dlg, IDCANCEL); |
380 |
return TRUE; |
381 |
} |
382 |
break; |
383 |
} |
384 |
return FALSE; |
385 |
} |
386 |
|
387 |
// |
388 |
// ���j���[�R�}���h���� |
389 |
// |
390 |
static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd) { |
391 |
switch (cmd) { |
392 |
case ID_MENU_SETUP: |
393 |
switch (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SETUP_RECURRINGCOMMAND), |
394 |
hWin, RecurringCommandSetting, (LPARAM)NULL)) { |
395 |
case IDOK: |
396 |
break; |
397 |
case IDCANCEL: |
398 |
break; |
399 |
case -1: |
400 |
MessageBox(hWin, "TTXRecurringCommand: Error", "Can't display dialog box.", |
401 |
MB_OK | MB_ICONEXCLAMATION); |
402 |
break; |
403 |
} |
404 |
return 1; |
405 |
} |
406 |
return 0; |
407 |
} |
408 |
|
409 |
static TTXExports Exports = { |
410 |
sizeof(TTXExports), |
411 |
ORDER, |
412 |
|
413 |
TTXInit, |
414 |
NULL, // TTXGetUIHooks, |
415 |
TTXGetSetupHooks, |
416 |
TTXOpenTCP, |
417 |
TTXCloseTCP, |
418 |
NULL, // TTXSetWinSize, |
419 |
TTXModifyMenu, |
420 |
NULL, // TTXModifyPopupMenu, |
421 |
TTXProcessCommand, |
422 |
NULL, // TTXEnd, |
423 |
NULL, // TTXSetCommandLine, |
424 |
TTXOpenFile, |
425 |
TTXCloseFile |
426 |
}; |
427 |
|
428 |
BOOL __declspec(dllexport) PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports) { |
429 |
int size = sizeof(Exports) - sizeof(exports->size); |
430 |
/* do version checking if necessary */ |
431 |
/* if (Version!=TTVERSION) return FALSE; */ |
432 |
|
433 |
if (size > exports->size) { |
434 |
size = exports->size; |
435 |
} |
436 |
memcpy((char FAR *)exports + sizeof(exports->size), |
437 |
(char FAR *)&Exports + sizeof(exports->size), size); |
438 |
return TRUE; |
439 |
} |
440 |
|
441 |
BOOL WINAPI DllMain(HANDLE hInstance, |
442 |
ULONG ul_reason_for_call, |
443 |
LPVOID lpReserved) |
444 |
{ |
445 |
switch( ul_reason_for_call ) { |
446 |
case DLL_THREAD_ATTACH: |
447 |
/* do thread initialization */ |
448 |
break; |
449 |
case DLL_THREAD_DETACH: |
450 |
/* do thread cleanup */ |
451 |
break; |
452 |
case DLL_PROCESS_ATTACH: |
453 |
/* do process initialization */ |
454 |
DoCover_IsDebuggerPresent(); |
455 |
hInst = hInstance; |
456 |
pvar = &InstVar; |
457 |
break; |
458 |
case DLL_PROCESS_DETACH: |
459 |
/* do process cleanup */ |
460 |
break; |
461 |
} |
462 |
return TRUE; |
463 |
} |