OSDN Git Service

Merge commit '03151a6ab14a8ba2d0c163d97e596ae093003712' into test
[ffftp/ffftp.git] / misc.c
1 /*=============================================================================\r
2 *\r
3 *                                                       その他の汎用サブルーチン\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 #define STRICT\r
31 #include <stdio.h>\r
32 #include <stdlib.h>\r
33 #include <stdarg.h>\r
34 #include <string.h>\r
35 #include <mbstring.h>\r
36 // IPv6対応\r
37 //#include <winsock.h>\r
38 #include <winsock2.h>\r
39 #include <windowsx.h>\r
40 #include <commctrl.h>\r
41 #include <shlobj.h>\r
42 #include <locale.h>\r
43 \r
44 #include "common.h"\r
45 #include "resource.h"\r
46 \r
47 #include <htmlhelp.h>\r
48 #include "helpid.h"\r
49 \r
50 // UTF-8対応\r
51 #undef __MBSWRAPPER_H__\r
52 #include "mbswrapper.h"\r
53 \r
54 \r
55 \r
56 /*===== 入力ダイアログデータのストラクチャ =====*/\r
57 \r
58 typedef struct {\r
59         char Title[80];                 /* ダイアログのタイトル */\r
60         char Str[FMAX_PATH+1];  /* デフォルト文字列/入力された文字列(Output) */\r
61         int MaxLen;                             /* 文字列の最長 */\r
62         int Anonymous;                  /* Anonymousフラグ(Output) */\r
63 } DIALOGDATA;\r
64 \r
65 /*===== プロトタイプ =====*/\r
66 \r
67 // 64ビット対応\r
68 //static BOOL CALLBACK InputDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam);\r
69 static INT_PTR CALLBACK InputDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam);\r
70 \r
71 /*===== 外部参照 =====*/\r
72 \r
73 extern HWND hHelpWin;\r
74 \r
75 /*===== ローカルなワーク =====*/\r
76 \r
77 static DIALOGDATA *DialogData;          /* 入力ダイアログデータ */\r
78 static int HelpPage;\r
79 \r
80 \r
81 \r
82 /*----- 入力ダイアログを表示 --------------------------------------------------\r
83 *\r
84 *       Parameter\r
85 *               int Res : ダイアログボックスのID\r
86 *               HWND hWnd : 親ウインドウのウインドウハンドル\r
87 *               char *Title : ウインドウタイトル (NULL=設定しない)\r
88 *               char *Buf : エディットボックスの初期文字列/入力文字列を返すバッファ\r
89 *               int Max : バッファのサイズ (FMAX_PATH+1以下であること)\r
90 *               int *Flg : フラグの初期値/フラグを返すワーク\r
91 *               int Help : ヘルプのコンテキスト番号\r
92 *\r
93 *       Return Value\r
94 *               int ステータス (YES/NO=取り消し)\r
95 *\r
96 *       Note\r
97 *               ダイアログは1個のEditBoxと1個のButtonを持つものを使う\r
98 *----------------------------------------------------------------------------*/\r
99 \r
100 int InputDialogBox(int Res, HWND hWnd, char *Title, char *Buf, int Max, int *Flg, int Help)\r
101 {\r
102         int Ret;\r
103         DIALOGDATA dData;\r
104 \r
105         dData.MaxLen = Max;\r
106         memset(dData.Str, NUL, FMAX_PATH+1);\r
107         strncpy(dData.Str, Buf, FMAX_PATH);\r
108         strcpy(dData.Title, "");\r
109         if(Title != NULL)\r
110                 strcpy(dData.Title, Title);\r
111         dData.Anonymous = *Flg;\r
112         DialogData = &dData;\r
113         HelpPage = Help;\r
114 \r
115         Ret = DialogBox(GetFtpInst(), MAKEINTRESOURCE(Res), hWnd, InputDialogCallBack);\r
116 \r
117         if(Ret == YES)\r
118         {\r
119                 memset(Buf, NUL, Max);\r
120                 strncpy(Buf, dData.Str, Max-1);\r
121                 *Flg = dData.Anonymous;\r
122         }\r
123         return(Ret);\r
124 }\r
125 \r
126 \r
127 /*----- 入力ダイアログのコールバック ------------------------------------------\r
128 *\r
129 *       Parameter\r
130 *               HWND hDlg : ウインドウハンドル\r
131 *               UINT message : メッセージ番号\r
132 *               WPARAM wParam : メッセージの WPARAM 引数\r
133 *               LPARAM lParam : メッセージの LPARAM 引数\r
134 *\r
135 *       Return Value\r
136 *               BOOL TRUE/FALSE\r
137 *----------------------------------------------------------------------------*/\r
138 \r
139 // 64ビット対応\r
140 //static BOOL CALLBACK InputDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)\r
141 static INT_PTR CALLBACK InputDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)\r
142 {\r
143         char Tmp[FMAX_PATH+1];\r
144 \r
145         switch (iMessage)\r
146         {\r
147                 case WM_INITDIALOG :\r
148                         if(strlen(DialogData->Title) != 0)\r
149                                 SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)DialogData->Title);\r
150                         SendDlgItemMessage(hDlg, INP_INPSTR, EM_LIMITTEXT, DialogData->MaxLen-1, 0);\r
151                         SendDlgItemMessage(hDlg, INP_INPSTR, WM_SETTEXT, 0, (LPARAM)DialogData->Str);\r
152                         SendDlgItemMessage(hDlg, INP_ANONYMOUS, BM_SETCHECK, DialogData->Anonymous, 0);\r
153                         return(TRUE);\r
154 \r
155                 case WM_COMMAND :\r
156                         switch(GET_WM_COMMAND_ID(wParam, lParam))\r
157                         {\r
158                                 case IDOK :\r
159                                         SendDlgItemMessage(hDlg, INP_INPSTR, WM_GETTEXT, DialogData->MaxLen, (LPARAM)DialogData->Str);\r
160                                         DialogData->Anonymous = SendDlgItemMessage(hDlg, INP_ANONYMOUS, BM_GETCHECK, 0, 0);\r
161                                         EndDialog(hDlg, YES);\r
162                                         break;\r
163 \r
164                                 case IDCANCEL :\r
165                                         EndDialog(hDlg, NO);\r
166                                         break;\r
167 \r
168                                 case IDHELP :\r
169                                         hHelpWin = HtmlHelp(NULL, AskHelpFilePath(), HH_HELP_CONTEXT, HelpPage);\r
170                                         break;\r
171 \r
172                                 case INP_BROWSE :\r
173                                         if(SelectDir(hDlg, Tmp, FMAX_PATH) == TRUE)\r
174                                                 SendDlgItemMessage(hDlg, INP_INPSTR, WM_SETTEXT, 0, (LPARAM)Tmp);\r
175                                         break;\r
176                         }\r
177             return(TRUE);\r
178         }\r
179         return(FALSE);\r
180 }\r
181 \r
182 \r
183 /*----- [実行]と[取消]だけのダイアログの共通コールバック関数 --------------\r
184 *\r
185 *       Parameter\r
186 *               HWND hDlg : ウインドウハンドル\r
187 *               UINT message : メッセージ番号\r
188 *               WPARAM wParam : メッセージの WPARAM 引数\r
189 *               LPARAM lParam : メッセージの LPARAM 引数\r
190 *\r
191 *       Return Value\r
192 *               BOOL TRUE/FALSE\r
193 *----------------------------------------------------------------------------*/\r
194 \r
195 // 64ビット対応\r
196 //BOOL CALLBACK ExeEscDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
197 INT_PTR CALLBACK ExeEscDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
198 {\r
199         switch (message)\r
200         {\r
201                 case WM_INITDIALOG :\r
202                         return(TRUE);\r
203 \r
204                 case WM_COMMAND :\r
205                         switch(GET_WM_COMMAND_ID(wParam, lParam))\r
206                         {\r
207                                 case IDOK :\r
208                                         EndDialog(hDlg, YES);\r
209                                         break;\r
210 \r
211                                 case IDCANCEL :\r
212                                         EndDialog(hDlg, NO);\r
213                                         break;\r
214                         }\r
215                         return(TRUE);\r
216         }\r
217     return(FALSE);\r
218 }\r
219 \r
220 \r
221 /*----- [実行]と[取消]だけのダイアログの共通コールバック関数(テキスト表示つき)\r
222 *\r
223 *       Parameter\r
224 *               HWND hDlg : ウインドウハンドル\r
225 *               UINT message : メッセージ番号\r
226 *               WPARAM wParam : メッセージの WPARAM 引数\r
227 *               LPARAM lParam : メッセージの LPARAM 引数\r
228 *\r
229 *       Return Value\r
230 *               BOOL TRUE/FALSE\r
231 *----------------------------------------------------------------------------*/\r
232 \r
233 // 64ビット対応\r
234 //BOOL CALLBACK ExeEscTextDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
235 INT_PTR CALLBACK ExeEscTextDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
236 {\r
237         switch (message)\r
238         {\r
239                 case WM_INITDIALOG :\r
240                         SendDlgItemMessage(hDlg, COMMON_TEXT, WM_SETTEXT, 0, lParam);\r
241                         return(TRUE);\r
242 \r
243                 case WM_COMMAND :\r
244                         switch(GET_WM_COMMAND_ID(wParam, lParam))\r
245                         {\r
246                                 case IDOK :\r
247                                         EndDialog(hDlg, YES);\r
248                                         break;\r
249 \r
250                                 case IDCANCEL :\r
251                                         EndDialog(hDlg, NO);\r
252                                         break;\r
253                         }\r
254                         return(TRUE);\r
255         }\r
256     return(FALSE);\r
257 }\r
258 \r
259 \r
260 /*----- 文字列の最後に "\" を付ける -------------------------------------------\r
261 *\r
262 *       Parameter\r
263 *               char *Str : 文字列\r
264 *\r
265 *       Return Value\r
266 *               なし\r
267 *\r
268 *       Note\r
269 *               オリジナルの文字列 char *Str が変更されます。\r
270 *----------------------------------------------------------------------------*/\r
271 \r
272 void SetYenTail(char *Str)\r
273 {\r
274         if(_mbscmp(_mbsninc(Str, _mbslen(Str) - 1), "\\") != 0)\r
275                 strcat(Str, "\\");\r
276 \r
277         return;;\r
278 }\r
279 \r
280 \r
281 /*----- 文字列の最後の "\" を取り除く -----------------------------------------\r
282 *\r
283 *       Parameter\r
284 *               char *Str : 文字列\r
285 *\r
286 *       Return Value\r
287 *               なし\r
288 *\r
289 *       Note\r
290 *               オリジナルの文字列 char *Str が変更されます。\r
291 *----------------------------------------------------------------------------*/\r
292 \r
293 void RemoveYenTail(char *Str)\r
294 {\r
295         char *Pos;\r
296 \r
297         if(strlen(Str) > 0)\r
298         {\r
299                 Pos = _mbsninc(Str, _mbslen(Str) - 1);\r
300                 if(_mbscmp(Pos, "\\") == 0)\r
301                         *Pos = NUL;\r
302         }\r
303         return;;\r
304 }\r
305 \r
306 \r
307 /*----- 文字列の最後に "/" を付ける -------------------------------------------\r
308 *\r
309 *       Parameter\r
310 *               char *Str : 文字列\r
311 *\r
312 *       Return Value\r
313 *               なし\r
314 *\r
315 *       Note\r
316 *               オリジナルの文字列 char *Str が変更されます。\r
317 *----------------------------------------------------------------------------*/\r
318 \r
319 void SetSlashTail(char *Str)\r
320 {\r
321 #if defined(HAVE_TANDEM)\r
322     /* Tandem では / の代わりに . を追加 */\r
323         if(AskHostType() == HTYPE_TANDEM) {\r
324                 if(_mbscmp(_mbsninc(Str, _mbslen(Str) - 1), ".") != 0)\r
325                         strcat(Str, ".");\r
326         } else\r
327 #endif\r
328         if(_mbscmp(_mbsninc(Str, _mbslen(Str) - 1), "/") != 0)\r
329                 strcat(Str, "/");\r
330 \r
331         return;\r
332 }\r
333 \r
334 \r
335 /*----- 文字列から改行コードを取り除く ----------------------------------------\r
336 *\r
337 *       Parameter\r
338 *               char *Str : 文字列\r
339 *\r
340 *       Return Value\r
341 *               なし\r
342 *\r
343 *       Note\r
344 *               オリジナルの文字列 char *Str が変更されます。\r
345 *----------------------------------------------------------------------------*/\r
346 \r
347 void RemoveReturnCode(char *Str)\r
348 {\r
349         char *Pos;\r
350 \r
351         if((Pos = strchr(Str, 0x0D)) != NULL)\r
352                 *Pos = NUL;\r
353         if((Pos = strchr(Str, 0x0A)) != NULL)\r
354                 *Pos = NUL;\r
355         return;\r
356 }\r
357 \r
358 \r
359 /*----- 文字列内の特定の文字を全て置き換える ----------------------------------\r
360 *\r
361 *       Parameter\r
362 *               char *Str : 文字列\r
363 *               char Src : 検索文字\r
364 *               char Dst : 置換文字\r
365 *\r
366 *       Return Value\r
367 *               なし\r
368 *----------------------------------------------------------------------------*/\r
369 \r
370 void ReplaceAll(char *Str, char Src, char Dst)\r
371 {\r
372         char *Pos;\r
373 \r
374 /* Tandem ではノード名の変換を行わない */\r
375 /* 最初の1文字が \ でもそのままにする */\r
376 #if defined(HAVE_TANDEM)\r
377         if (AskRealHostType() == HTYPE_TANDEM && strlen(Str) > 0)\r
378                 Str++;\r
379 #endif\r
380         while((Pos = _mbschr(Str, Src)) != NULL)\r
381                 *Pos = Dst;\r
382         return;\r
383 }\r
384 \r
385 \r
386 /*----- 数字もしくは特定の1文字かチェック ------------------------------------\r
387 *\r
388 *       Parameter\r
389 *               int Ch : チェックする文字\r
390 *               int Sym : 記号\r
391 *\r
392 *       Return Value\r
393 *               int ステータス\r
394 *                       0=数字でも特定の記号でもない\r
395 *----------------------------------------------------------------------------*/\r
396 \r
397 int IsDigitSym(int Ch, int Sym)\r
398 {\r
399         int Ret;\r
400 \r
401         if((Ret = IsDigit(Ch)) == 0)\r
402         {\r
403                 if((Sym != NUL) && (Sym == Ch))\r
404                         Ret = 1;\r
405         }\r
406         return(Ret);\r
407 }\r
408 \r
409 \r
410 /*----- 文字列が全て同じ文字かチェック ----------------------------------------\r
411 *\r
412 *       Parameter\r
413 *               char *Str : 文字列\r
414 *               int Ch : 文字\r
415 *\r
416 *       Return Value\r
417 *               int ステータス\r
418 *                       YES/NO\r
419 *----------------------------------------------------------------------------*/\r
420 \r
421 int StrAllSameChar(char *Str, char Ch)\r
422 {\r
423         int Ret;\r
424 \r
425         Ret = YES;\r
426         while(*Str != NUL)\r
427         {\r
428                 if(*Str != Ch)\r
429                 {\r
430                         Ret = NO;\r
431                         break;\r
432                 }\r
433                 Str++;\r
434         }\r
435         return(Ret);\r
436 }\r
437 \r
438 \r
439 /*----- 文字列の末尾のスペースを削除 ------------------------------------------\r
440 *\r
441 *       Parameter\r
442 *               char *Str : 文字列\r
443 *\r
444 *       Return Value\r
445 *               なし\r
446 *----------------------------------------------------------------------------*/\r
447 \r
448 void RemoveTailingSpaces(char *Str)\r
449 {\r
450         char *Pos;\r
451 \r
452         Pos = Str + strlen(Str);\r
453         while(--Pos > Str)\r
454         {\r
455                 if(*Pos != ' ')\r
456                         break;\r
457                 *Pos = NUL;\r
458         }\r
459         return;\r
460 }\r
461 \r
462 \r
463 /*----- 大文字/小文字を区別しないstrstr --------------------------------------\r
464 *\r
465 *       Parameter\r
466 *               char *s1 : 文字列1\r
467 *               char *s2 : 文字列2\r
468 *\r
469 *       Return Value\r
470 *               char *文字列1中で文字列2が見つかった位置\r
471 *                       NULL=見つからなかった\r
472 *----------------------------------------------------------------------------*/\r
473 \r
474 char *stristr(char *s1, char *s2)\r
475 {\r
476         char *Ret;\r
477 \r
478         Ret = NULL;\r
479         while(*s1 != NUL)\r
480         {\r
481                 if((tolower(*s1) == tolower(*s2)) &&\r
482                    (_strnicmp(s1, s2, strlen(s2)) == 0))\r
483                 {\r
484                         Ret = s1;\r
485                         break;\r
486                 }\r
487                 s1++;\r
488         }\r
489         return(Ret);\r
490 }\r
491 \r
492 \r
493 /*----- 文字列中のスペースで区切られた次のフィールドを返す --------------------\r
494 *\r
495 *       Parameter\r
496 *               char *Str : 文字列\r
497 *\r
498 *       Return Value\r
499 *               char *次のフィールド\r
500 *                       NULL=見つからなかった\r
501 *----------------------------------------------------------------------------*/\r
502 \r
503 char *GetNextField(char *Str)\r
504 {\r
505         if((Str = strchr(Str, ' ')) != NULL)\r
506         {\r
507                 while(*Str == ' ')\r
508                 {\r
509                         if(*Str == NUL)\r
510                         {\r
511                                 Str = NULL;\r
512                                 break;\r
513                         }\r
514                         Str++;\r
515                 }\r
516         }\r
517         return(Str);\r
518 }\r
519 \r
520 \r
521 /*----- 現在のフィールドの文字列をコピーする ----------------------------------\r
522 *\r
523 *       Parameter\r
524 *               char *Str : 文字列\r
525 *               char *Buf : コピー先\r
526 *               int Max : 最大文字数\r
527 *\r
528 *       Return Value\r
529 *               int ステータス\r
530 *                       FFFTP_SUCCESS/FFFTP_FAIL=長さが長すぎる\r
531 *----------------------------------------------------------------------------*/\r
532 \r
533 int GetOneField(char *Str, char *Buf, int Max)\r
534 {\r
535         int Sts;\r
536         char *Pos;\r
537 \r
538         Sts = FFFTP_FAIL;\r
539         if((Pos = strchr(Str, ' ')) == NULL)\r
540         {\r
541                 if((int)strlen(Str) <= Max)\r
542                 {\r
543                         strcpy(Buf, Str);\r
544                         Sts = FFFTP_SUCCESS;\r
545                 }\r
546         }\r
547         else\r
548         {\r
549                 if(Pos - Str <= Max)\r
550                 {\r
551                         strncpy(Buf, Str, Pos - Str);\r
552                         *(Buf + (Pos - Str)) = NUL;\r
553                         Sts = FFFTP_SUCCESS;\r
554                 }\r
555         }\r
556         return(Sts);\r
557 }\r
558 \r
559 \r
560 /*----- カンマを取り除く ------------------------------------------------------\r
561 *\r
562 *       Parameter\r
563 *               char *Str : 文字列\r
564 *\r
565 *       Return Value\r
566 *               なし\r
567 *----------------------------------------------------------------------------*/\r
568 \r
569 void RemoveComma(char *Str)\r
570 {\r
571         char *Put;\r
572 \r
573         Put = Str;\r
574         while(*Str != NUL)\r
575         {\r
576                 if(*Str != ',')\r
577                 {\r
578                         *Put = *Str;\r
579                         Put++;\r
580                 }\r
581                 Str++;\r
582         }\r
583         *Put = NUL;\r
584         return;\r
585 }\r
586 \r
587 \r
588 /*----- パス名の中のファイル名の先頭を返す ------------------------------------\r
589 *\r
590 *       Parameter\r
591 *               char *Path : パス名\r
592 *\r
593 *       Return Value\r
594 *               char *ファイル名の先頭\r
595 *\r
596 *       Note\r
597 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
598 *----------------------------------------------------------------------------*/\r
599 \r
600 char *GetFileName(char *Path)\r
601 {\r
602         char *Pos;\r
603 \r
604         if((Pos = _mbschr(Path, ':')) != NULL)\r
605                 Path = Pos + 1;\r
606 \r
607         if((Pos = _mbsrchr(Path, '\\')) != NULL)\r
608                 Path = Pos + 1;\r
609 \r
610         if((Pos = _mbsrchr(Path, '/')) != NULL)\r
611                 Path = Pos + 1;\r
612 \r
613 #if defined(HAVE_TANDEM)\r
614         /* Tandem は . がデリミッタとなる */\r
615         if((AskHostType() == HTYPE_TANDEM) && ((Pos = _mbsrchr(Path, '.')) != NULL))\r
616                 Path = Pos + 1;\r
617 #endif\r
618         return(Path);\r
619 }\r
620 \r
621 \r
622 /*----- ツールの表示名を返す --------------------------------------------------\r
623 *\r
624 *       Parameter\r
625 *               char *Path : パス名\r
626 *\r
627 *       Return Value\r
628 *               char * : 表示名\r
629 *----------------------------------------------------------------------------*/\r
630 \r
631 char *GetToolName(char *Path)\r
632 {\r
633         char *Pos;\r
634 \r
635         if((Pos = _mbschr(Path, ':')) != NULL)\r
636                 Path = Pos + 1;\r
637 \r
638         if((Pos = _mbsrchr(Path, '\\')) != NULL)\r
639                 Path = Pos + 1;\r
640 \r
641         return(Path);\r
642 }\r
643 \r
644 \r
645 /*----- パス名の中の拡張子の先頭を返す ----------------------------------------\r
646 *\r
647 *       Parameter\r
648 *               char *Path : パス名\r
649 *\r
650 *       Return Value\r
651 *               char *拡張子の先頭\r
652 *----------------------------------------------------------------------------*/\r
653 \r
654 char *GetFileExt(char *Path)\r
655 {\r
656         char *Ret;\r
657 \r
658         Ret = _mbschr(Path, NUL);\r
659         if((_mbscmp(Path, ".") != 0) &&\r
660            (_mbscmp(Path, "..") != 0))\r
661         {\r
662                 while((Path = _mbschr(Path, '.')) != NULL)\r
663                 {\r
664                         Path++;\r
665                         Ret = Path;\r
666                 }\r
667         }\r
668         return(Ret);\r
669 }\r
670 \r
671 \r
672 /*----- パス名からファイル名を取り除く ----------------------------------------\r
673 *\r
674 *       Parameter\r
675 *               char *Path : パス名\r
676 *               char *Buf : ファイル名を除いたパス名のコピー先\r
677 *\r
678 *       Return Value\r
679 *               なし\r
680 *\r
681 *       Note\r
682 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
683 *----------------------------------------------------------------------------*/\r
684 \r
685 void RemoveFileName(char *Path, char *Buf)\r
686 {\r
687         char *Pos;\r
688 \r
689         strcpy(Buf, Path);\r
690 \r
691         if((Pos = _mbsrchr(Buf, '/')) != NULL)\r
692                 *Pos = NUL;\r
693         else if((Pos = _mbsrchr(Buf, '\\')) != NULL)\r
694         {\r
695                 if((Pos == Buf) || \r
696                    ((Pos != Buf) && (*(Pos - 1) != ':')))\r
697                         *Pos = NUL;\r
698         }\r
699         return;\r
700 }\r
701 \r
702 \r
703 /*----- 上位ディレクトリのパス名を取得 ----------------------------------------\r
704 *\r
705 *       Parameter\r
706 *               char *Path : パス名\r
707 *\r
708 *       Return Value\r
709 *               なし\r
710 *\r
711 *       Note\r
712 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
713 *               最初の "\"や"/"は残す\r
714 *                       例) "/pub"   --> "/"\r
715 *                       例) "C:\DOS" --> "C:\"\r
716 *----------------------------------------------------------------------------*/\r
717 \r
718 void GetUpperDir(char *Path)\r
719 {\r
720         char *Top;\r
721         char *Pos;\r
722 \r
723         if(((Top = _mbschr(Path, '/')) != NULL) ||\r
724            ((Top = _mbschr(Path, '\\')) != NULL))\r
725         {\r
726                 Top++;\r
727                 if(((Pos = _mbsrchr(Top, '/')) != NULL) ||\r
728                    ((Pos = _mbsrchr(Top, '\\')) != NULL))\r
729                         *Pos = NUL;\r
730                 else\r
731                         *Top = NUL;\r
732         }\r
733         return;\r
734 }\r
735 \r
736 \r
737 /*----- 上位ディレクトリのパス名を取得 ----------------------------------------\r
738 *\r
739 *       Parameter\r
740 *               char *Path : パス名\r
741 *\r
742 *       Return Value\r
743 *               なし\r
744 *\r
745 *       Note\r
746 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
747 *               最初の "\"や"/"も消す\r
748 *                       例) "/pub"   --> ""\r
749 *                       例) "C:\DOS" --> "C:"\r
750 *----------------------------------------------------------------------------*/\r
751 \r
752 void GetUpperDirEraseTopSlash(char *Path)\r
753 {\r
754         char *Pos;\r
755 \r
756         if(((Pos = _mbsrchr(Path, '/')) != NULL) ||\r
757            ((Pos = _mbsrchr(Path, '\\')) != NULL))\r
758                 *Pos = NUL;\r
759         else\r
760                 *Path = NUL;\r
761 \r
762         return;\r
763 }\r
764 \r
765 \r
766 /*----- ディレクトリの階層数を返す --------------------------------------------\r
767 *\r
768 *       Parameter\r
769 *               char *Path : パス名\r
770 *\r
771 *       Return Value\r
772 *               なし\r
773 *\r
774 *       Note\r
775 *               単に '\' と '/'の数を返すだけ\r
776 *----------------------------------------------------------------------------*/\r
777 \r
778 int AskDirLevel(char *Path)\r
779 {\r
780         char *Pos;\r
781         int Level;\r
782 \r
783         Level = 0;\r
784         while(((Pos = _mbschr(Path, '/')) != NULL) ||\r
785                   ((Pos = _mbschr(Path, '\\')) != NULL))\r
786         {\r
787                 Path = Pos + 1;\r
788                 Level++;\r
789         }\r
790         return(Level);\r
791 }\r
792 \r
793 \r
794 /*----- ファイルサイズを文字列に変換する --------------------------------------\r
795 *\r
796 *       Parameter\r
797 *               double Size : ファイルサイズ\r
798 *               char *Buf : 文字列を返すバッファ\r
799 *\r
800 *       Return Value\r
801 *               なし\r
802 *----------------------------------------------------------------------------*/\r
803 \r
804 void MakeSizeString(double Size, char *Buf)\r
805 {\r
806         if(Size >= (1024*1024))\r
807         {\r
808                 Size /= (1024*1024);\r
809                 sprintf(Buf, "%.2fM Bytes", Size);\r
810         }\r
811         else if (Size >= 1024)\r
812         {\r
813                 Size /= 1024;\r
814                 sprintf(Buf, "%.2fK Bytes", Size);\r
815         }\r
816         else\r
817                 sprintf(Buf, "%.0f Bytes", Size);\r
818 \r
819         return;\r
820 }\r
821 \r
822 \r
823 /*----- StaticTextの領域に収まるようにパス名を整形して表示 --------------------\r
824 *\r
825 *       Parameter\r
826 *               HWND hWnd : ウインドウハンドル\r
827 *               char *Str : 文字列 (長さはFMAX_PATH以下)\r
828 *\r
829 *       Return Value\r
830 *               なし\r
831 *----------------------------------------------------------------------------*/\r
832 \r
833 void DispStaticText(HWND hWnd, char *Str)\r
834 {\r
835         char Buf[FMAX_PATH+1];\r
836         char *Pos;\r
837         char *Tmp;\r
838         RECT Rect;\r
839         SIZE fSize;\r
840         HDC hDC;\r
841         int Force;\r
842 \r
843         GetClientRect(hWnd, &Rect);\r
844         Rect.right -= Rect.left;\r
845 \r
846         hDC = GetDC(hWnd);\r
847         strcpy(Buf, Str);\r
848         Pos = Buf;\r
849         Force = NO;\r
850         while(Force == NO)\r
851         {\r
852                 GetTextExtentPoint32(hDC, Pos, strlen(Pos), &fSize);\r
853 \r
854                 if(fSize.cx <= Rect.right)\r
855                         break;\r
856 \r
857                 if(_mbslen(Pos) <= 4)\r
858                         Force = YES;\r
859                 else\r
860                 {\r
861                         Pos = _mbsninc(Pos, 4);\r
862                         if((Tmp = _mbschr(Pos, '\\')) == NULL)\r
863                                 Tmp = _mbschr(Pos, '/');\r
864 \r
865                         if(Tmp == NULL)\r
866                                 Tmp = _mbsninc(Pos, 4);\r
867 \r
868                         Pos = Tmp - 3;\r
869                         memset(Pos, '.', 3);\r
870                 }\r
871         }\r
872         ReleaseDC(hWnd, hDC);\r
873 \r
874         SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)Pos);\r
875         return;\r
876 }\r
877 \r
878 \r
879 /*----- 文字列アレイの長さを求める --------------------------------------------\r
880 *\r
881 *       Parameter\r
882 *               char *Str : 文字列アレイ (末尾はNUL2つ)\r
883 *\r
884 *       Return Value\r
885 *               int 長さ\r
886 *\r
887 *       Note\r
888 *               終端の2つのNULのうちの最後の物は数えない\r
889 *                       StrMultiLen("") = 0\r
890 *                       StrMultiLen("abc\0xyz\0") = 8\r
891 *                       StrMultiLen("abc") = 終端が2つのNULでないので求められない\r
892 *----------------------------------------------------------------------------*/\r
893 \r
894 int StrMultiLen(char *Str)\r
895 {\r
896         int Len;\r
897         int Tmp;\r
898 \r
899         Len = 0;\r
900         while(*Str != NUL)\r
901         {\r
902                 Tmp = strlen(Str) + 1;\r
903                 Str += Tmp;\r
904                 Len += Tmp;\r
905         }\r
906         return(Len);\r
907 }\r
908 \r
909 \r
910 /*----- RECTをクライアント座標からスクリーン座標に変換 ------------------------\r
911 *\r
912 *       Parameter\r
913 *               HWND hWnd : ウインドウハンドル\r
914 *               RECT *Rect : RECT\r
915 *\r
916 *       Return Value\r
917 *               なし\r
918 *----------------------------------------------------------------------------*/\r
919 \r
920 void RectClientToScreen(HWND hWnd, RECT *Rect)\r
921 {\r
922         POINT Tmp;\r
923 \r
924         Tmp.x = Rect->left;\r
925         Tmp.y = Rect->top;\r
926         ClientToScreen(hWnd, &Tmp);\r
927         Rect->left = Tmp.x;\r
928         Rect->top = Tmp.y;\r
929 \r
930         Tmp.x = Rect->right;\r
931         Tmp.y = Rect->bottom;\r
932         ClientToScreen(hWnd, &Tmp);\r
933         Rect->right = Tmp.x;\r
934         Rect->bottom = Tmp.y;\r
935 \r
936         return;\r
937 }\r
938 \r
939 \r
940 /*----- 16進文字をバイナリに変換 ----------------------------------------------\r
941 *\r
942 *       Parameter\r
943 *               char Ch : 16進文字\r
944 *\r
945 *       Return Value\r
946 *               int バイナリ値\r
947 *----------------------------------------------------------------------------*/\r
948 \r
949 int hex2bin(char Ch)\r
950 {\r
951         int Ret;\r
952 \r
953         if((Ch >= '0') && (Ch <= '9'))\r
954                 Ret = Ch - '0';\r
955         else if((Ch >= 'A') && (Ch <= 'F'))\r
956                 Ret = Ch - 'A' + 10;\r
957         else if((Ch >= 'a') && (Ch <= 'f'))\r
958                 Ret = Ch - 'a' + 10;\r
959 \r
960         return(Ret);\r
961 }\r
962 \r
963 \r
964 /*----- UNC文字列を分解する ------------------------------------------------\r
965 *\r
966 *       Parameter\r
967 *               char *unc : UNC文字列\r
968 *               char *Host : ホスト名をコピーするバッファ (サイズは HOST_ADRS_LEN+1)\r
969 *               char *Path : パス名をコピーするバッファ (サイズは FMAX_PATH+1)\r
970 *               char *File : ファイル名をコピーするバッファ (サイズは FMAX_PATH+1)\r
971 *               char *User : ユーザ名をコピーするバッファ (サイズは USER_NAME_LEN+1)\r
972 *               char *Pass : パスワードをコピーするバッファ (サイズは PASSWORD_LEN+1)\r
973 *               int *Port : ポート番号をコピーするバッファ\r
974 *\r
975 *       Return Value\r
976 *               int ステータス\r
977 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
978 *\r
979 *       "\"は全て"/"に置き換える\r
980 *----------------------------------------------------------------------------*/\r
981 \r
982 int SplitUNCpath(char *unc, char *Host, char *Path, char *File, char *User, char *Pass, int *Port)\r
983 {\r
984         int Sts;\r
985         char *Pos1;\r
986         char *Pos2;\r
987         char Tmp[FMAX_PATH+1];\r
988 \r
989         memset(Host, NUL, HOST_ADRS_LEN+1);\r
990         memset(Path, NUL, FMAX_PATH+1);\r
991         memset(File, NUL, FMAX_PATH+1);\r
992         memset(User, NUL, USER_NAME_LEN+1);\r
993         memset(Pass, NUL, PASSWORD_LEN+1);\r
994         *Port = PORT_NOR;\r
995 \r
996         ReplaceAll(unc, '\\', '/');\r
997 \r
998         if((Pos1 = _mbsstr(unc, "//")) != NULL)\r
999                 Pos1 += 2;\r
1000         else\r
1001                 Pos1 = unc;\r
1002 \r
1003         if((Pos2 = _mbschr(Pos1, '@')) != NULL)\r
1004         {\r
1005                 memset(Tmp, NUL, FMAX_PATH+1);\r
1006                 memcpy(Tmp, Pos1, Pos2-Pos1);\r
1007                 Pos1 = Pos2 + 1;\r
1008 \r
1009                 if((Pos2 = _mbschr(Tmp, ':')) != NULL)\r
1010                 {\r
1011                         memcpy(User, Tmp, min1(Pos2-Tmp, USER_NAME_LEN));\r
1012                         strncpy(Pass, Pos2+1, PASSWORD_LEN);\r
1013                 }\r
1014                 else\r
1015                         strncpy(User, Tmp, USER_NAME_LEN);\r
1016         }\r
1017 \r
1018         // IPv6対応\r
1019         if((Pos2 = _mbschr(Pos1, '[')) != NULL && Pos2 < _mbschr(Pos1, ':'))\r
1020         {\r
1021                 Pos1 = Pos2 + 1;\r
1022                 if((Pos2 = _mbschr(Pos2, ']')) != NULL)\r
1023                 {\r
1024                         memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1025                         Pos1 = Pos2 + 1;\r
1026                 }\r
1027         }\r
1028 \r
1029         if((Pos2 = _mbschr(Pos1, ':')) != NULL)\r
1030         {\r
1031                 // IPv6対応\r
1032 //              memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1033                 if(strlen(Host) == 0)\r
1034                         memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1035                 Pos2++;\r
1036                 if(IsDigit(*Pos2))\r
1037                 {\r
1038                         *Port = atoi(Pos2);\r
1039                         while(*Pos2 != NUL)\r
1040                         {\r
1041                                 if(IsDigit(*Pos2) == 0)\r
1042                                         break;\r
1043                                 Pos2++;\r
1044                         }\r
1045                 }\r
1046                 RemoveFileName(Pos2, Path);\r
1047                 strncpy(File, GetFileName(Pos2), FMAX_PATH);\r
1048         }\r
1049         else if((Pos2 = _mbschr(Pos1, '/')) != NULL)\r
1050         {\r
1051                 // IPv6対応\r
1052 //              memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1053                 if(strlen(Host) == 0)\r
1054                         memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1055                 RemoveFileName(Pos2, Path);\r
1056                 strncpy(File, GetFileName(Pos2), FMAX_PATH);\r
1057         }\r
1058         else\r
1059         {\r
1060                 // IPv6対応\r
1061 //              strncpy(Host, Pos1, HOST_ADRS_LEN);\r
1062                 if(strlen(Host) == 0)\r
1063                         strncpy(Host, Pos1, HOST_ADRS_LEN);\r
1064         }\r
1065 \r
1066         Sts = FFFTP_FAIL;\r
1067         if(strlen(Host) > 0)\r
1068                 Sts = FFFTP_SUCCESS;\r
1069 \r
1070         return(Sts);\r
1071 }\r
1072 \r
1073 \r
1074 /*----- 日付文字列(JST)をFILETIME(UTC)に変換 ----------------------------------\r
1075 *\r
1076 *       Parameter\r
1077 *               char *Time : 日付文字列 ("yyyy/mm/dd hh:mm")\r
1078 *               FILETIME *Buf : ファイルタイムを返すワーク\r
1079 *\r
1080 *       Return Value\r
1081 *               int ステータス\r
1082 *                       YES/NO=日付情報がなかった\r
1083 *----------------------------------------------------------------------------*/\r
1084 \r
1085 int TimeString2FileTime(char *Time, FILETIME *Buf)\r
1086 {\r
1087         SYSTEMTIME sTime;\r
1088         FILETIME fTime;\r
1089         int Ret;\r
1090 \r
1091         Ret = NO;\r
1092     Buf->dwLowDateTime = 0;\r
1093     Buf->dwHighDateTime = 0;\r
1094 \r
1095         if(strlen(Time) >= 16)\r
1096         {\r
1097                 if(IsDigit(Time[0]) && IsDigit(Time[5]) && IsDigit(Time[8]) && \r
1098                    IsDigit(Time[12]) && IsDigit(Time[14]))\r
1099                 {\r
1100                         Ret = YES;\r
1101                 }\r
1102 \r
1103                 sTime.wYear = atoi(Time);\r
1104                 sTime.wMonth = atoi(Time + 5);\r
1105                 sTime.wDay = atoi(Time + 8);\r
1106                 if(Time[11] != ' ')\r
1107                         sTime.wHour = atoi(Time + 11);\r
1108                 else\r
1109                         sTime.wHour = atoi(Time + 12);\r
1110                 sTime.wMinute = atoi(Time + 14);\r
1111                 sTime.wSecond = 0;\r
1112                 sTime.wMilliseconds = 0;\r
1113 \r
1114                 SystemTimeToFileTime(&sTime, &fTime);\r
1115                 LocalFileTimeToFileTime(&fTime, Buf);\r
1116         }\r
1117         return(Ret);\r
1118 }\r
1119 \r
1120 \r
1121 /*----- FILETIME(UTC)を日付文字列(JST)に変換 ----------------------------------\r
1122 *\r
1123 *       Parameter\r
1124 *               FILETIME *Time : ファイルタイム\r
1125 *               char *Buf : 日付文字列を返すワーク\r
1126 *               int Mode : モード (DISPFORM_xxx)\r
1127 *               int InfoExist : 情報があるかどうか (FINFO_xxx)\r
1128 *\r
1129 *       Return Value\r
1130 *               なし\r
1131 *----------------------------------------------------------------------------*/\r
1132 \r
1133 void FileTime2TimeString(FILETIME *Time, char *Buf, int Mode, int InfoExist)\r
1134 {\r
1135         SYSTEMTIME sTime;\r
1136         FILETIME fTime;\r
1137 \r
1138         if(Mode == DISPFORM_LEGACY)\r
1139         {\r
1140                 if((Time->dwLowDateTime == 0) && (Time->dwHighDateTime == 0))\r
1141                         InfoExist = 0;\r
1142 \r
1143                 /* "yyyy/mm/dd hh:mm" */\r
1144                 FileTimeToLocalFileTime(Time, &fTime);\r
1145                 FileTimeToSystemTime(&fTime, &sTime);\r
1146 \r
1147                 if(InfoExist & FINFO_DATE)\r
1148                         sprintf(Buf, "%04d/%02d/%02d ", sTime.wYear, sTime.wMonth, sTime.wDay);\r
1149                 else\r
1150                         sprintf(Buf, "           ");\r
1151 \r
1152                 if(InfoExist & FINFO_TIME)\r
1153                         sprintf(Buf+11, "%2d:%02d", sTime.wHour, sTime.wMinute);\r
1154                 else\r
1155                         sprintf(Buf+11, "     ");\r
1156         }\r
1157         else\r
1158         {\r
1159 //              if (!strftime((char *)str, 100, "%c",  (const struct tm *)thetime))\r
1160 //                      SetTaskMsg("strftime が失敗しました!\n");\r
1161         }\r
1162         return;\r
1163 }\r
1164 \r
1165 \r
1166 /*----- ファイルタイムを指定タイムゾーンのローカルタイムからGMTに変換 ---------\r
1167 *\r
1168 *       Parameter\r
1169 *               FILETIME *Time : ファイルタイム\r
1170 *               int TimeZone : タイムゾーン\r
1171 *\r
1172 *       Return Value\r
1173 *               なし\r
1174 *----------------------------------------------------------------------------*/\r
1175 \r
1176 void SpecificLocalFileTime2FileTime(FILETIME *Time, int TimeZone)\r
1177 {\r
1178         unsigned __int64 Tmp64;\r
1179 \r
1180         Tmp64 = (unsigned __int64)Time->dwLowDateTime +\r
1181                         ((unsigned __int64)Time->dwHighDateTime << 32);\r
1182 \r
1183         Tmp64 -= (__int64)TimeZone * (__int64)36000000000;\r
1184 \r
1185         Time->dwHighDateTime = (DWORD)(Tmp64 >> 32);\r
1186         Time->dwLowDateTime = (DWORD)(Tmp64 & 0xFFFFFFFF);\r
1187 \r
1188         return;\r
1189 }\r
1190 \r
1191 \r
1192 /*----- 属性文字列を値に変換 --------------------------------------------------\r
1193 *\r
1194 *       Parameter\r
1195 *               char *Str : 属性文字列 ("rwxrwxrwx")\r
1196 *\r
1197 *       Return Value\r
1198 *               int 値\r
1199 *----------------------------------------------------------------------------*/\r
1200 \r
1201 int AttrString2Value(char *Str)\r
1202 {\r
1203         int Ret;\r
1204         char Tmp[10];\r
1205 \r
1206         Ret = 0;\r
1207         memset(Tmp, 0, 10);\r
1208         strncpy(Tmp, Str, 9);\r
1209 \r
1210         if(Tmp[0] != '-')\r
1211                 Ret |= 0x400;\r
1212         if(Tmp[1] != '-')\r
1213                 Ret |= 0x200;\r
1214         if(Tmp[2] != '-')\r
1215                 Ret |= 0x100;\r
1216 \r
1217         if(Tmp[3] != '-')\r
1218                 Ret |= 0x40;\r
1219         if(Tmp[4] != '-')\r
1220                 Ret |= 0x20;\r
1221         if(Tmp[5] != '-')\r
1222                 Ret |= 0x10;\r
1223 \r
1224         if(Tmp[6] != '-')\r
1225                 Ret |= 0x4;\r
1226         if(Tmp[7] != '-')\r
1227                 Ret |= 0x2;\r
1228         if(Tmp[8] != '-')\r
1229                 Ret |= 0x1;\r
1230 \r
1231         return(Ret);\r
1232 }\r
1233 \r
1234 \r
1235 /*----- 属性の値を文字列に変換 ------------------------------------------------\r
1236 *\r
1237 *       Parameter\r
1238 *               int Attr : 属性の値\r
1239 *               char *Buf : 属性文字列をセットするバッファ ("rwxrwxrwx")\r
1240 *\r
1241 *       Return Value\r
1242 *               int 値\r
1243 *----------------------------------------------------------------------------*/\r
1244 \r
1245 void AttrValue2String(int Attr, char *Buf)\r
1246 {\r
1247         strcpy(Buf, "---------");\r
1248 \r
1249         if(Attr & 0x400)\r
1250                 Buf[0] = 'r';\r
1251         if(Attr & 0x200)\r
1252                 Buf[1] = 'w';\r
1253         if(Attr & 0x100)\r
1254                 Buf[2] = 'x';\r
1255 \r
1256         if(Attr & 0x40)\r
1257                 Buf[3] = 'r';\r
1258         if(Attr & 0x20)\r
1259                 Buf[4] = 'w';\r
1260         if(Attr & 0x10)\r
1261                 Buf[5] = 'x';\r
1262 \r
1263         if(Attr & 0x4)\r
1264                 Buf[6] = 'r';\r
1265         if(Attr & 0x2)\r
1266                 Buf[7] = 'w';\r
1267         if(Attr & 0x1)\r
1268                 Buf[8] = 'x';\r
1269 \r
1270         return;\r
1271 }\r
1272 \r
1273 \r
1274 /*----- INIファイル文字列を整形 -----------------------------------------------\r
1275 *\r
1276 *       Parameter\r
1277 *               char *Str : 文字列\r
1278 *\r
1279 *       Return Value\r
1280 *               なし\r
1281 *----------------------------------------------------------------------------*/\r
1282 \r
1283 void FormatIniString(char *Str)\r
1284 {\r
1285         char *Put;\r
1286 \r
1287         Put = Str;\r
1288         while(*Str != NUL)\r
1289         {\r
1290                 if((*Str != ' ') && (*Str != '\t') && (*Str != '\n'))\r
1291                         *Put++ = *Str;\r
1292                 if(*Str++ == '=')\r
1293                         break;\r
1294         }\r
1295 \r
1296         while(*Str != NUL)\r
1297         {\r
1298                 if((*Str != 0x22) && (*Str != '\n'))\r
1299                         *Put++ = *Str;\r
1300                 Str++;\r
1301         }\r
1302         *Put = NUL;\r
1303 \r
1304         return;\r
1305 }\r
1306 \r
1307 \r
1308 /*----- ファイル選択 ----------------------------------------------------------\r
1309 *\r
1310 *       Parameter\r
1311 *               HWND hWnd : ウインドウハンドル\r
1312 *               char *Fname : ファイル名を返すバッファ\r
1313 *               char *Title : タイトル\r
1314 *               char *Filters : フィルター文字列\r
1315 *               char *Ext : デフォルト拡張子\r
1316 *               int Flags : 追加するフラグ\r
1317 *               int Save : 「開く」か「保存」か (0=開く, 1=保存)\r
1318 *\r
1319 *       Return Value\r
1320 *               int ステータス\r
1321 *                       TRUE/FALSE=取消\r
1322 *----------------------------------------------------------------------------*/\r
1323 \r
1324 int SelectFile(HWND hWnd, char *Fname, char *Title, char *Filters, char *Ext, int Flags, int Save)\r
1325 {\r
1326         OPENFILENAME OpenFile;\r
1327         char Tmp[FMAX_PATH+1];\r
1328         char Cur[FMAX_PATH+1];\r
1329         int Sts;\r
1330 \r
1331         GetCurrentDirectory(FMAX_PATH, Cur);\r
1332 \r
1333         strcpy(Tmp, Fname);\r
1334         OpenFile.lStructSize = sizeof(OPENFILENAME);\r
1335         OpenFile.hwndOwner = hWnd;\r
1336         OpenFile.hInstance = 0;\r
1337         OpenFile.lpstrFilter = Filters;\r
1338         OpenFile.lpstrCustomFilter = NULL;\r
1339         OpenFile.nFilterIndex = 1;\r
1340         OpenFile.lpstrFile = Tmp;\r
1341         OpenFile.nMaxFile = FMAX_PATH;\r
1342         OpenFile.lpstrFileTitle = NULL;\r
1343         OpenFile.nMaxFileTitle = 0;\r
1344         OpenFile.lpstrInitialDir = NULL;\r
1345         OpenFile.lpstrTitle = Title;\r
1346         OpenFile.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | Flags;\r
1347         OpenFile.nFileOffset = 0;\r
1348         OpenFile.nFileExtension = 0;\r
1349         OpenFile.lpstrDefExt = Ext;\r
1350         OpenFile.lCustData = 0;\r
1351         OpenFile.lpfnHook = NULL;\r
1352         OpenFile.lpTemplateName = NULL;\r
1353 \r
1354         if(Save == 0)\r
1355         {\r
1356                 if((Sts = GetOpenFileName(&OpenFile)) == TRUE)\r
1357                         strcpy(Fname,Tmp);\r
1358         }\r
1359         else\r
1360         {\r
1361                 if((Sts = GetSaveFileName(&OpenFile)) == TRUE)\r
1362                         strcpy(Fname,Tmp);\r
1363         }\r
1364         SetCurrentDirectory(Cur);\r
1365         return(Sts);\r
1366 }\r
1367 \r
1368 \r
1369 /*----- ディレクトリを選択 ----------------------------------------------------\r
1370 *\r
1371 *       Parameter\r
1372 *               HWND hWnd : ウインドウハンドル\r
1373 *               char *Buf : ディレクトリ名を返すバッファ(初期ディレクトリ名)\r
1374 *               int MaxLen : バッファのサイズ\r
1375 *\r
1376 *       Return Value\r
1377 *               int ステータス\r
1378 *                       TRUE/FALSE=取消\r
1379 *----------------------------------------------------------------------------*/\r
1380 \r
1381 int SelectDir(HWND hWnd, char *Buf, int MaxLen)\r
1382 {\r
1383         char Tmp[FMAX_PATH+1];\r
1384         char Cur[FMAX_PATH+1];\r
1385         BROWSEINFO  Binfo;\r
1386         LPITEMIDLIST lpIdll;\r
1387         int Sts;\r
1388         LPMALLOC lpMalloc;\r
1389 \r
1390         Sts = FALSE;\r
1391         GetCurrentDirectory(FMAX_PATH, Cur);\r
1392 \r
1393         if(SHGetMalloc(&lpMalloc) == NOERROR)\r
1394         {\r
1395                 Binfo.hwndOwner = hWnd;\r
1396                 Binfo.pidlRoot = NULL;\r
1397                 Binfo.pszDisplayName = Tmp;\r
1398                 Binfo.lpszTitle = MSGJPN185;\r
1399                 Binfo.ulFlags = BIF_RETURNONLYFSDIRS;\r
1400                 Binfo.lpfn = NULL;\r
1401                 Binfo.lParam = 0;\r
1402                 Binfo.iImage = 0;\r
1403                 if((lpIdll = SHBrowseForFolder(&Binfo)) != NULL)\r
1404                 {\r
1405                         SHGetPathFromIDList(lpIdll, Tmp);\r
1406                         memset(Buf, NUL, MaxLen);\r
1407                         strncpy(Buf, Tmp, MaxLen-1);\r
1408                         Sts = TRUE;\r
1409                         lpMalloc->lpVtbl->Free(lpMalloc, lpIdll);\r
1410             }\r
1411             lpMalloc->lpVtbl->Release(lpMalloc);\r
1412                 SetCurrentDirectory(Cur);\r
1413         }\r
1414         return(Sts);\r
1415 }\r
1416 \r
1417 \r
1418 /*----- 値に関連付けられたラジオボタンをチェックする --------------------------\r
1419 *\r
1420 *       Parameter\r
1421 *               HWND hDlg : ダイアログボックスのウインドウハンドル\r
1422 *               int Value : 値\r
1423 *               const RADIOBUTTON *Buttons : ラジオボタンと値の関連付けテーブル\r
1424 *               int Num : ボタンの数\r
1425 *\r
1426 *       Return Value\r
1427 *               なし\r
1428 *\r
1429 *       Note\r
1430 *               値に関連付けられたボタンが無い時は、テーブルの最初に登録されているボタ\r
1431 *               ンをチェックする\r
1432 *----------------------------------------------------------------------------*/\r
1433 \r
1434 void SetRadioButtonByValue(HWND hDlg, int Value, const RADIOBUTTON *Buttons, int Num)\r
1435 {\r
1436         int i;\r
1437         int Def;\r
1438 \r
1439         Def = Buttons->ButID;\r
1440         for(i = 0; i < Num; i++)\r
1441         {\r
1442                 if(Value == Buttons->Value)\r
1443                 {\r
1444                         SendDlgItemMessage(hDlg, Buttons->ButID, BM_SETCHECK, 1, 0);\r
1445                         /* ラジオボタンを変更した時に他の項目のハイドなどを行なう事が      */\r
1446                         /* あるので、そのために WM_COMMAND を送る                                          */\r
1447                         SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(Buttons->ButID, 0), 0);\r
1448                         break;\r
1449                 }\r
1450                 Buttons++;\r
1451         }\r
1452         if(i == Num)\r
1453         {\r
1454                 SendDlgItemMessage(hDlg, Def, BM_SETCHECK, 1, 0);\r
1455                 SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(Def, 0), 0);\r
1456         }\r
1457         return;\r
1458 }\r
1459 \r
1460 \r
1461 /*----- チェックされているボタンに関連付けられた値を返す ----------------------\r
1462 *\r
1463 *       Parameter\r
1464 *               HWND hDlg : ダイアログボックスのウインドウハンドル\r
1465 *               const RADIOBUTTON *Buttons : ラジオボタンと値の関連付けテーブル\r
1466 *               int Num : ボタンの数\r
1467 *\r
1468 *       Return Value\r
1469 *               int 値\r
1470 *\r
1471 *       Note\r
1472 *               どのボタンもチェックされていない時は、テーブルの最初に登録されているボ\r
1473 *               タンの値を返す\r
1474 *----------------------------------------------------------------------------*/\r
1475 \r
1476 int AskRadioButtonValue(HWND hDlg, const RADIOBUTTON *Buttons, int Num)\r
1477 {\r
1478         int i;\r
1479         int Ret;\r
1480 \r
1481         Ret = Buttons->Value;\r
1482         for(i = 0; i < Num; i++)\r
1483         {\r
1484                 if(SendDlgItemMessage(hDlg, Buttons->ButID, BM_GETCHECK, 0, 0) == 1)\r
1485                 {\r
1486                         Ret = Buttons->Value;\r
1487                         break;\r
1488                 }\r
1489                 Buttons++;\r
1490         }\r
1491         return(Ret);\r
1492 }\r
1493 \r
1494 \r
1495 /*----- 16進文字列を数値に変換 ----------------------------------------------\r
1496 *\r
1497 *       Parameter\r
1498 *               char *Str : 文字列\r
1499 *\r
1500 *       Return Value\r
1501 *               int 値\r
1502 *----------------------------------------------------------------------------*/\r
1503 \r
1504 int xtoi(char *Str)\r
1505 {\r
1506         int Ret;\r
1507 \r
1508         Ret = 0;\r
1509         while(*Str != NUL)\r
1510         {\r
1511                 Ret *= 0x10;\r
1512                 if((*Str >= '0') && (*Str <= '9'))\r
1513                         Ret += *Str - '0';\r
1514                 else if((*Str >= 'A') && (*Str <= 'F'))\r
1515                         Ret += *Str - 'A' + 10;\r
1516                 else if((*Str >= 'a') && (*Str <= 'f'))\r
1517                         Ret += *Str - 'a' + 10;\r
1518                 else\r
1519                         break;\r
1520 \r
1521                 Str++;\r
1522         }\r
1523         return(Ret);\r
1524 }\r
1525 \r
1526 \r
1527 /*----- ファイルが読み取り可能かどうかを返す ----------------------------------\r
1528 *\r
1529 *       Parameter\r
1530 *               char *Fname : ファイル名\r
1531 *\r
1532 *       Return Value\r
1533 *               int ステータス\r
1534 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1535 *----------------------------------------------------------------------------*/\r
1536 \r
1537 int CheckFileReadable(char *Fname)\r
1538 {\r
1539         int Sts;\r
1540         HANDLE iFileHandle;\r
1541         SECURITY_ATTRIBUTES Sec;\r
1542 \r
1543         Sts = FFFTP_FAIL;\r
1544 \r
1545         Sec.nLength = sizeof(SECURITY_ATTRIBUTES);\r
1546         Sec.lpSecurityDescriptor = NULL;\r
1547         Sec.bInheritHandle = FALSE;\r
1548 \r
1549         if((iFileHandle = CreateFile(Fname, GENERIC_READ,\r
1550                 FILE_SHARE_READ|FILE_SHARE_WRITE, &Sec, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)\r
1551         {\r
1552                 Sts = FFFTP_SUCCESS;\r
1553                 CloseHandle(iFileHandle);\r
1554         }\r
1555         return(Sts);\r
1556 }\r
1557 \r
1558 \r
1559 \r
1560 \r
1561 \r
1562 int max1(int n, int m)\r
1563 {\r
1564         if(n > m)\r
1565                 return(n);\r
1566         else\r
1567                 return(m);\r
1568 }\r
1569 \r
1570 \r
1571 \r
1572 int min1(int n, int m)\r
1573 {\r
1574         if(n < m)\r
1575                 return(n);\r
1576         else\r
1577                 return(m);\r
1578 }\r
1579 \r
1580 \r
1581 void ExcEndianDWORD(DWORD *x)\r
1582 {\r
1583         BYTE *Pos;\r
1584         BYTE Tmp;\r
1585 \r
1586         Pos = (BYTE *)x;\r
1587         Tmp = *(Pos + 0);\r
1588         *(Pos + 0) = *(Pos + 3);\r
1589         *(Pos + 3) = Tmp;\r
1590         Tmp = *(Pos + 1);\r
1591         *(Pos + 1) = *(Pos + 2);\r
1592         *(Pos + 2) = Tmp;\r
1593         return;\r
1594 }\r
1595 \r
1596 \r
1597 \r
1598 \r
1599 /*----- int値の入れ替え -------------------------------------------------------\r
1600 *\r
1601 *       Parameter\r
1602 *               int *Num1 : 数値1\r
1603 *               int *Num2 : 数値2\r
1604 *\r
1605 *       Return Value\r
1606 *               なし\r
1607 *----------------------------------------------------------------------------*/\r
1608 \r
1609 void SwapInt(int *Num1, int *Num2)\r
1610 {\r
1611         int Tmp;\r
1612 \r
1613         Tmp = *Num1;\r
1614         *Num1 = *Num2;\r
1615         *Num2 = Tmp;\r
1616         return;\r
1617 }\r
1618 \r
1619 \r
1620 /*----- 指定されたフォルダがあるかどうかチェック -------------------------------\r
1621 *\r
1622 *       Parameter\r
1623 *               char *Path : パス\r
1624 *\r
1625 *       Return Value\r
1626 *               int ステータス (YES/NO)\r
1627 *----------------------------------------------------------------------------*/\r
1628 \r
1629 int IsFolderExist(char *Path)\r
1630 {\r
1631         int Sts;\r
1632         char Tmp[FMAX_PATH+1];\r
1633         DWORD Attr;\r
1634 \r
1635         Sts = YES;\r
1636         if(strlen(Path) > 0)\r
1637         {\r
1638                 strcpy(Tmp, Path);\r
1639                 if(_mbscmp(Tmp+1, ":\\") != 0)\r
1640                         RemoveYenTail(Tmp);\r
1641 \r
1642                 Attr = GetFileAttributes(Tmp);\r
1643                 if((Attr == 0xFFFFFFFF) || ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0))\r
1644                         Sts = NO;\r
1645         }\r
1646         return(Sts);\r
1647 }\r
1648 \r
1649 \r
1650 /*----- テーブルにしたがって数値を登録 -----------------------------------------\r
1651 *\r
1652 *       Parameter\r
1653 *               int x : 数値\r
1654 *               int Dir : 変換方向\r
1655 *               INTCONVTBL *Tbl : テーブル\r
1656 *               int Num : テーブルの数値の数\r
1657 *\r
1658 *       Return Value\r
1659 *               int 数値\r
1660 *----------------------------------------------------------------------------*/\r
1661 \r
1662 int ConvertNum(int x, int Dir, const INTCONVTBL *Tbl, int Num)\r
1663 {\r
1664         int i;\r
1665         int Ret;\r
1666 \r
1667         Ret = x;\r
1668         for(i = 0; i < Num; i++)\r
1669         {\r
1670                 if((Dir == 0) && (Tbl->Num1 == x))\r
1671                 {\r
1672                         Ret = Tbl->Num2;\r
1673                         break;\r
1674                 }\r
1675                 else if((Dir == 1) && (Tbl->Num2 == x))\r
1676                 {\r
1677                         Ret = Tbl->Num1;\r
1678                         break;\r
1679                 }\r
1680                 Tbl++;\r
1681         }\r
1682         return(Ret);\r
1683 }\r
1684 \r
1685 \r
1686 \r
1687 \r
1688 \r
1689 \r
1690 /*----- ファイルをゴミ箱に削除 ------------------------------------------------\r
1691 *\r
1692 *       Parameter\r
1693 *               char *Path : ファイル名\r
1694 *\r
1695 *       Return Value\r
1696 *               int ステータス (0=正常終了)\r
1697 *----------------------------------------------------------------------------*/\r
1698 \r
1699 int MoveFileToTrashCan(char *Path)\r
1700 {\r
1701         SHFILEOPSTRUCT FileOp;\r
1702         char Tmp[FMAX_PATH+2];\r
1703 \r
1704         memset(Tmp, 0, FMAX_PATH+2);\r
1705         strcpy(Tmp, Path);\r
1706         FileOp.hwnd = NULL;\r
1707         FileOp.wFunc = FO_DELETE;\r
1708         FileOp.pFrom = Tmp;\r
1709         FileOp.pTo = "";\r
1710         FileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO;\r
1711         FileOp.lpszProgressTitle = "";\r
1712         return(SHFileOperation(&FileOp));\r
1713 }\r
1714 \r
1715 \r
1716 \r
1717 \r
1718 LONGLONG MakeLongLong(DWORD High, DWORD Low)\r
1719 {\r
1720         LONGLONG z;\r
1721         LONGLONG x1, y1;\r
1722 \r
1723         x1 = (LONGLONG)Low;\r
1724         y1 = (LONGLONG)High;\r
1725         z = x1 | (y1 << 32);\r
1726         return(z);\r
1727 }\r
1728 \r
1729 \r
1730 char *MakeNumString(LONGLONG Num, char *Buf, BOOL Comma)\r
1731 {\r
1732         int i;\r
1733         char *Pos;\r
1734 \r
1735         Pos = Buf;\r
1736         *Pos = '\0';\r
1737 \r
1738         i = 1;\r
1739         do\r
1740         {\r
1741                 *Pos++ = (char)(Num % 10) + '0';\r
1742                 Num /= 10;\r
1743                 if((Comma == TRUE) && ((i % 3) == 0) && (Num != 0))\r
1744                         *Pos++ = ',';\r
1745                 i++;\r
1746         }\r
1747         while(Num != 0);\r
1748         *Pos = NUL;\r
1749         _strrev(Buf);\r
1750 \r
1751         return(Buf);\r
1752 }\r
1753 \r
1754 \r
1755 // 異なるファイルが表示されるバグ修正\r
1756 \r
1757 // ShellExecute等で使用されるファイル名を修正\r
1758 // UNCでない場合に末尾の半角スペースは無視されるため拡張子が補完されなくなるまで半角スペースを追加\r
1759 // 現在UNC対応の予定は無い\r
1760 char* MakeDistinguishableFileName(char* Out, char* In)\r
1761 {\r
1762         char* Fname;\r
1763         char Tmp[FMAX_PATH+1];\r
1764         char Tmp2[FMAX_PATH+3];\r
1765         HANDLE hFind;\r
1766         WIN32_FIND_DATA Find;\r
1767         if(strlen(GetFileExt(GetFileName(In))) > 0)\r
1768                 strcpy(Out, In);\r
1769         else\r
1770         {\r
1771                 Fname = GetFileName(In);\r
1772                 strcpy(Tmp, In);\r
1773                 strcpy(Tmp2, Tmp);\r
1774                 strcat(Tmp2, ".*");\r
1775                 while(strlen(Tmp) < FMAX_PATH && (hFind = FindFirstFile(Tmp2, &Find)) != INVALID_HANDLE_VALUE)\r
1776                 {\r
1777                         do\r
1778                         {\r
1779                                 if(strcmp(Find.cFileName, Fname) != 0)\r
1780                                         break;\r
1781                         }\r
1782                         while(FindNextFile(hFind, &Find));\r
1783                         FindClose(hFind);\r
1784                         if(strcmp(Find.cFileName, Fname) != 0)\r
1785                         {\r
1786                                 strcat(Tmp, " ");\r
1787                                 strcpy(Tmp2, Tmp);\r
1788                                 strcat(Tmp2, ".*");\r
1789                         }\r
1790                         else\r
1791                                 break;\r
1792                 }\r
1793                 strcpy(Out, Tmp);\r
1794         }\r
1795         return Out;\r
1796 }\r
1797 \r
1798 // 環境依存の不具合対策\r
1799 char* GetAppTempPath(char* Buf)\r
1800 {\r
1801         char Temp[32];\r
1802         GetTempPath(MAX_PATH, Buf);\r
1803         SetYenTail(Buf);\r
1804         sprintf(Temp, "ffftp%08x", GetCurrentProcessId());\r
1805         strcat(Buf, Temp);\r
1806         return Buf;\r
1807 }\r
1808 \r
1809 #if defined(HAVE_TANDEM)\r
1810 /*----- ファイルサイズからEXTENTサイズの計算を行う ----------------------------\r
1811 *\r
1812 *       Parameter\r
1813 *               LONGLONG Size : ファイルサイズ\r
1814 *\r
1815 *       Return Value\r
1816 *               なし\r
1817 *----------------------------------------------------------------------------*/\r
1818 void CalcExtentSize(TRANSPACKET *Pkt, LONGLONG Size)\r
1819 {\r
1820         LONGLONG extent;\r
1821 \r
1822         /* EXTENTS(4,28) MAXEXTENTS 978 */\r
1823         if(Size < 56025088) {\r
1824                 Pkt->PriExt = DEF_PRIEXT;\r
1825                 Pkt->SecExt = DEF_SECEXT;\r
1826                 Pkt->MaxExt = DEF_MAXEXT;\r
1827         } else {\r
1828                 /* 増加余地を残すため Used 75% 近辺になるように EXTENT サイズを調整) */\r
1829                 extent = (LONGLONG)(Size / ((DEF_MAXEXT * 0.75) * 2048LL));\r
1830                 /* 28未満にすると誤差でFile Fullになる可能性がある */\r
1831                 if(extent < 28)\r
1832                         extent = 28;\r
1833 \r
1834                 Pkt->PriExt = (int)extent;\r
1835                 Pkt->SecExt = (int)extent;\r
1836                 Pkt->MaxExt = DEF_MAXEXT;\r
1837         }\r
1838 }\r
1839 #endif\r