OSDN Git Service

Fix bugs of simultaneous connection.
[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(_mbscmp(_mbsninc(Str, _mbslen(Str) - 1), "/") != 0)\r
322                 strcat(Str, "/");\r
323 \r
324         return;\r
325 }\r
326 \r
327 \r
328 /*----- 文字列から改行コードを取り除く ----------------------------------------\r
329 *\r
330 *       Parameter\r
331 *               char *Str : 文字列\r
332 *\r
333 *       Return Value\r
334 *               なし\r
335 *\r
336 *       Note\r
337 *               オリジナルの文字列 char *Str が変更されます。\r
338 *----------------------------------------------------------------------------*/\r
339 \r
340 void RemoveReturnCode(char *Str)\r
341 {\r
342         char *Pos;\r
343 \r
344         if((Pos = strchr(Str, 0x0D)) != NULL)\r
345                 *Pos = NUL;\r
346         if((Pos = strchr(Str, 0x0A)) != NULL)\r
347                 *Pos = NUL;\r
348         return;\r
349 }\r
350 \r
351 \r
352 /*----- 文字列内の特定の文字を全て置き換える ----------------------------------\r
353 *\r
354 *       Parameter\r
355 *               char *Str : 文字列\r
356 *               char Src : 検索文字\r
357 *               char Dst : 置換文字\r
358 *\r
359 *       Return Value\r
360 *               なし\r
361 *----------------------------------------------------------------------------*/\r
362 \r
363 void ReplaceAll(char *Str, char Src, char Dst)\r
364 {\r
365         char *Pos;\r
366 \r
367         while((Pos = _mbschr(Str, Src)) != NULL)\r
368                 *Pos = Dst;\r
369         return;\r
370 }\r
371 \r
372 \r
373 /*----- 数字もしくは特定の1文字かチェック ------------------------------------\r
374 *\r
375 *       Parameter\r
376 *               int Ch : チェックする文字\r
377 *               int Sym : 記号\r
378 *\r
379 *       Return Value\r
380 *               int ステータス\r
381 *                       0=数字でも特定の記号でもない\r
382 *----------------------------------------------------------------------------*/\r
383 \r
384 int IsDigitSym(int Ch, int Sym)\r
385 {\r
386         int Ret;\r
387 \r
388         if((Ret = IsDigit(Ch)) == 0)\r
389         {\r
390                 if((Sym != NUL) && (Sym == Ch))\r
391                         Ret = 1;\r
392         }\r
393         return(Ret);\r
394 }\r
395 \r
396 \r
397 /*----- 文字列が全て同じ文字かチェック ----------------------------------------\r
398 *\r
399 *       Parameter\r
400 *               char *Str : 文字列\r
401 *               int Ch : 文字\r
402 *\r
403 *       Return Value\r
404 *               int ステータス\r
405 *                       YES/NO\r
406 *----------------------------------------------------------------------------*/\r
407 \r
408 int StrAllSameChar(char *Str, char Ch)\r
409 {\r
410         int Ret;\r
411 \r
412         Ret = YES;\r
413         while(*Str != NUL)\r
414         {\r
415                 if(*Str != Ch)\r
416                 {\r
417                         Ret = NO;\r
418                         break;\r
419                 }\r
420                 Str++;\r
421         }\r
422         return(Ret);\r
423 }\r
424 \r
425 \r
426 /*----- 文字列の末尾のスペースを削除 ------------------------------------------\r
427 *\r
428 *       Parameter\r
429 *               char *Str : 文字列\r
430 *\r
431 *       Return Value\r
432 *               なし\r
433 *----------------------------------------------------------------------------*/\r
434 \r
435 void RemoveTailingSpaces(char *Str)\r
436 {\r
437         char *Pos;\r
438 \r
439         Pos = Str + strlen(Str);\r
440         while(--Pos > Str)\r
441         {\r
442                 if(*Pos != ' ')\r
443                         break;\r
444                 *Pos = NUL;\r
445         }\r
446         return;\r
447 }\r
448 \r
449 \r
450 /*----- 大文字/小文字を区別しないstrstr --------------------------------------\r
451 *\r
452 *       Parameter\r
453 *               char *s1 : 文字列1\r
454 *               char *s2 : 文字列2\r
455 *\r
456 *       Return Value\r
457 *               char *文字列1中で文字列2が見つかった位置\r
458 *                       NULL=見つからなかった\r
459 *----------------------------------------------------------------------------*/\r
460 \r
461 char *stristr(char *s1, char *s2)\r
462 {\r
463         char *Ret;\r
464 \r
465         Ret = NULL;\r
466         while(*s1 != NUL)\r
467         {\r
468                 if((tolower(*s1) == tolower(*s2)) &&\r
469                    (_strnicmp(s1, s2, strlen(s2)) == 0))\r
470                 {\r
471                         Ret = s1;\r
472                         break;\r
473                 }\r
474                 s1++;\r
475         }\r
476         return(Ret);\r
477 }\r
478 \r
479 \r
480 /*----- 文字列中のスペースで区切られた次のフィールドを返す --------------------\r
481 *\r
482 *       Parameter\r
483 *               char *Str : 文字列\r
484 *\r
485 *       Return Value\r
486 *               char *次のフィールド\r
487 *                       NULL=見つからなかった\r
488 *----------------------------------------------------------------------------*/\r
489 \r
490 char *GetNextField(char *Str)\r
491 {\r
492         if((Str = strchr(Str, ' ')) != NULL)\r
493         {\r
494                 while(*Str == ' ')\r
495                 {\r
496                         if(*Str == NUL)\r
497                         {\r
498                                 Str = NULL;\r
499                                 break;\r
500                         }\r
501                         Str++;\r
502                 }\r
503         }\r
504         return(Str);\r
505 }\r
506 \r
507 \r
508 /*----- 現在のフィールドの文字列をコピーする ----------------------------------\r
509 *\r
510 *       Parameter\r
511 *               char *Str : 文字列\r
512 *               char *Buf : コピー先\r
513 *               int Max : 最大文字数\r
514 *\r
515 *       Return Value\r
516 *               int ステータス\r
517 *                       FFFTP_SUCCESS/FFFTP_FAIL=長さが長すぎる\r
518 *----------------------------------------------------------------------------*/\r
519 \r
520 int GetOneField(char *Str, char *Buf, int Max)\r
521 {\r
522         int Sts;\r
523         char *Pos;\r
524 \r
525         Sts = FFFTP_FAIL;\r
526         if((Pos = strchr(Str, ' ')) == NULL)\r
527         {\r
528                 if((int)strlen(Str) <= Max)\r
529                 {\r
530                         strcpy(Buf, Str);\r
531                         Sts = FFFTP_SUCCESS;\r
532                 }\r
533         }\r
534         else\r
535         {\r
536                 if(Pos - Str <= Max)\r
537                 {\r
538                         strncpy(Buf, Str, Pos - Str);\r
539                         *(Buf + (Pos - Str)) = NUL;\r
540                         Sts = FFFTP_SUCCESS;\r
541                 }\r
542         }\r
543         return(Sts);\r
544 }\r
545 \r
546 \r
547 /*----- カンマを取り除く ------------------------------------------------------\r
548 *\r
549 *       Parameter\r
550 *               char *Str : 文字列\r
551 *\r
552 *       Return Value\r
553 *               なし\r
554 *----------------------------------------------------------------------------*/\r
555 \r
556 void RemoveComma(char *Str)\r
557 {\r
558         char *Put;\r
559 \r
560         Put = Str;\r
561         while(*Str != NUL)\r
562         {\r
563                 if(*Str != ',')\r
564                 {\r
565                         *Put = *Str;\r
566                         Put++;\r
567                 }\r
568                 Str++;\r
569         }\r
570         *Put = NUL;\r
571         return;\r
572 }\r
573 \r
574 \r
575 /*----- パス名の中のファイル名の先頭を返す ------------------------------------\r
576 *\r
577 *       Parameter\r
578 *               char *Path : パス名\r
579 *\r
580 *       Return Value\r
581 *               char *ファイル名の先頭\r
582 *\r
583 *       Note\r
584 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
585 *----------------------------------------------------------------------------*/\r
586 \r
587 char *GetFileName(char *Path)\r
588 {\r
589         char *Pos;\r
590 \r
591         if((Pos = _mbschr(Path, ':')) != NULL)\r
592                 Path = Pos + 1;\r
593 \r
594         if((Pos = _mbsrchr(Path, '\\')) != NULL)\r
595                 Path = Pos + 1;\r
596 \r
597         if((Pos = _mbsrchr(Path, '/')) != NULL)\r
598                 Path = Pos + 1;\r
599 \r
600         return(Path);\r
601 }\r
602 \r
603 \r
604 /*----- ツールの表示名を返す --------------------------------------------------\r
605 *\r
606 *       Parameter\r
607 *               char *Path : パス名\r
608 *\r
609 *       Return Value\r
610 *               char * : 表示名\r
611 *----------------------------------------------------------------------------*/\r
612 \r
613 char *GetToolName(char *Path)\r
614 {\r
615         char *Pos;\r
616 \r
617         if((Pos = _mbschr(Path, ':')) != NULL)\r
618                 Path = Pos + 1;\r
619 \r
620         if((Pos = _mbsrchr(Path, '\\')) != NULL)\r
621                 Path = Pos + 1;\r
622 \r
623         return(Path);\r
624 }\r
625 \r
626 \r
627 /*----- パス名の中の拡張子の先頭を返す ----------------------------------------\r
628 *\r
629 *       Parameter\r
630 *               char *Path : パス名\r
631 *\r
632 *       Return Value\r
633 *               char *拡張子の先頭\r
634 *----------------------------------------------------------------------------*/\r
635 \r
636 char *GetFileExt(char *Path)\r
637 {\r
638         char *Ret;\r
639 \r
640         Ret = _mbschr(Path, NUL);\r
641         if((_mbscmp(Path, ".") != 0) &&\r
642            (_mbscmp(Path, "..") != 0))\r
643         {\r
644                 while((Path = _mbschr(Path, '.')) != NULL)\r
645                 {\r
646                         Path++;\r
647                         Ret = Path;\r
648                 }\r
649         }\r
650         return(Ret);\r
651 }\r
652 \r
653 \r
654 /*----- パス名からファイル名を取り除く ----------------------------------------\r
655 *\r
656 *       Parameter\r
657 *               char *Path : パス名\r
658 *               char *Buf : ファイル名を除いたパス名のコピー先\r
659 *\r
660 *       Return Value\r
661 *               なし\r
662 *\r
663 *       Note\r
664 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
665 *----------------------------------------------------------------------------*/\r
666 \r
667 void RemoveFileName(char *Path, char *Buf)\r
668 {\r
669         char *Pos;\r
670 \r
671         strcpy(Buf, Path);\r
672 \r
673         if((Pos = _mbsrchr(Buf, '/')) != NULL)\r
674                 *Pos = NUL;\r
675         else if((Pos = _mbsrchr(Buf, '\\')) != NULL)\r
676         {\r
677                 if((Pos == Buf) || \r
678                    ((Pos != Buf) && (*(Pos - 1) != ':')))\r
679                         *Pos = NUL;\r
680         }\r
681         return;\r
682 }\r
683 \r
684 \r
685 /*----- 上位ディレクトリのパス名を取得 ----------------------------------------\r
686 *\r
687 *       Parameter\r
688 *               char *Path : パス名\r
689 *\r
690 *       Return Value\r
691 *               なし\r
692 *\r
693 *       Note\r
694 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
695 *               最初の "\"や"/"は残す\r
696 *                       例) "/pub"   --> "/"\r
697 *                       例) "C:\DOS" --> "C:\"\r
698 *----------------------------------------------------------------------------*/\r
699 \r
700 void GetUpperDir(char *Path)\r
701 {\r
702         char *Top;\r
703         char *Pos;\r
704 \r
705         if(((Top = _mbschr(Path, '/')) != NULL) ||\r
706            ((Top = _mbschr(Path, '\\')) != NULL))\r
707         {\r
708                 Top++;\r
709                 if(((Pos = _mbsrchr(Top, '/')) != NULL) ||\r
710                    ((Pos = _mbsrchr(Top, '\\')) != NULL))\r
711                         *Pos = NUL;\r
712                 else\r
713                         *Top = NUL;\r
714         }\r
715         return;\r
716 }\r
717 \r
718 \r
719 /*----- 上位ディレクトリのパス名を取得 ----------------------------------------\r
720 *\r
721 *       Parameter\r
722 *               char *Path : パス名\r
723 *\r
724 *       Return Value\r
725 *               なし\r
726 *\r
727 *       Note\r
728 *               ディレクトリの区切り記号は "\" と "/" の両方が有効\r
729 *               最初の "\"や"/"も消す\r
730 *                       例) "/pub"   --> ""\r
731 *                       例) "C:\DOS" --> "C:"\r
732 *----------------------------------------------------------------------------*/\r
733 \r
734 void GetUpperDirEraseTopSlash(char *Path)\r
735 {\r
736         char *Pos;\r
737 \r
738         if(((Pos = _mbsrchr(Path, '/')) != NULL) ||\r
739            ((Pos = _mbsrchr(Path, '\\')) != NULL))\r
740                 *Pos = NUL;\r
741         else\r
742                 *Path = NUL;\r
743 \r
744         return;\r
745 }\r
746 \r
747 \r
748 /*----- ディレクトリの階層数を返す --------------------------------------------\r
749 *\r
750 *       Parameter\r
751 *               char *Path : パス名\r
752 *\r
753 *       Return Value\r
754 *               なし\r
755 *\r
756 *       Note\r
757 *               単に '\' と '/'の数を返すだけ\r
758 *----------------------------------------------------------------------------*/\r
759 \r
760 int AskDirLevel(char *Path)\r
761 {\r
762         char *Pos;\r
763         int Level;\r
764 \r
765         Level = 0;\r
766         while(((Pos = _mbschr(Path, '/')) != NULL) ||\r
767                   ((Pos = _mbschr(Path, '\\')) != NULL))\r
768         {\r
769                 Path = Pos + 1;\r
770                 Level++;\r
771         }\r
772         return(Level);\r
773 }\r
774 \r
775 \r
776 /*----- ファイルサイズを文字列に変換する --------------------------------------\r
777 *\r
778 *       Parameter\r
779 *               double Size : ファイルサイズ\r
780 *               char *Buf : 文字列を返すバッファ\r
781 *\r
782 *       Return Value\r
783 *               なし\r
784 *----------------------------------------------------------------------------*/\r
785 \r
786 void MakeSizeString(double Size, char *Buf)\r
787 {\r
788         if(Size >= (1024*1024))\r
789         {\r
790                 Size /= (1024*1024);\r
791                 sprintf(Buf, "%.2fM Bytes", Size);\r
792         }\r
793         else if (Size >= 1024)\r
794         {\r
795                 Size /= 1024;\r
796                 sprintf(Buf, "%.2fK Bytes", Size);\r
797         }\r
798         else\r
799                 sprintf(Buf, "%.0f Bytes", Size);\r
800 \r
801         return;\r
802 }\r
803 \r
804 \r
805 /*----- StaticTextの領域に収まるようにパス名を整形して表示 --------------------\r
806 *\r
807 *       Parameter\r
808 *               HWND hWnd : ウインドウハンドル\r
809 *               char *Str : 文字列 (長さはFMAX_PATH以下)\r
810 *\r
811 *       Return Value\r
812 *               なし\r
813 *----------------------------------------------------------------------------*/\r
814 \r
815 void DispStaticText(HWND hWnd, char *Str)\r
816 {\r
817         char Buf[FMAX_PATH+1];\r
818         char *Pos;\r
819         char *Tmp;\r
820         RECT Rect;\r
821         SIZE fSize;\r
822         HDC hDC;\r
823         int Force;\r
824 \r
825         GetClientRect(hWnd, &Rect);\r
826         Rect.right -= Rect.left;\r
827 \r
828         hDC = GetDC(hWnd);\r
829         strcpy(Buf, Str);\r
830         Pos = Buf;\r
831         Force = NO;\r
832         while(Force == NO)\r
833         {\r
834                 GetTextExtentPoint32(hDC, Pos, strlen(Pos), &fSize);\r
835 \r
836                 if(fSize.cx <= Rect.right)\r
837                         break;\r
838 \r
839                 if(_mbslen(Pos) <= 4)\r
840                         Force = YES;\r
841                 else\r
842                 {\r
843                         Pos = _mbsninc(Pos, 4);\r
844                         if((Tmp = _mbschr(Pos, '\\')) == NULL)\r
845                                 Tmp = _mbschr(Pos, '/');\r
846 \r
847                         if(Tmp == NULL)\r
848                                 Tmp = _mbsninc(Pos, 4);\r
849 \r
850                         Pos = Tmp - 3;\r
851                         memset(Pos, '.', 3);\r
852                 }\r
853         }\r
854         ReleaseDC(hWnd, hDC);\r
855 \r
856         SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)Pos);\r
857         return;\r
858 }\r
859 \r
860 \r
861 /*----- 文字列アレイの長さを求める --------------------------------------------\r
862 *\r
863 *       Parameter\r
864 *               char *Str : 文字列アレイ (末尾はNUL2つ)\r
865 *\r
866 *       Return Value\r
867 *               int 長さ\r
868 *\r
869 *       Note\r
870 *               終端の2つのNULのうちの最後の物は数えない\r
871 *                       StrMultiLen("") = 0\r
872 *                       StrMultiLen("abc\0xyz\0") = 8\r
873 *                       StrMultiLen("abc") = 終端が2つのNULでないので求められない\r
874 *----------------------------------------------------------------------------*/\r
875 \r
876 int StrMultiLen(char *Str)\r
877 {\r
878         int Len;\r
879         int Tmp;\r
880 \r
881         Len = 0;\r
882         while(*Str != NUL)\r
883         {\r
884                 Tmp = strlen(Str) + 1;\r
885                 Str += Tmp;\r
886                 Len += Tmp;\r
887         }\r
888         return(Len);\r
889 }\r
890 \r
891 \r
892 /*----- RECTをクライアント座標からスクリーン座標に変換 ------------------------\r
893 *\r
894 *       Parameter\r
895 *               HWND hWnd : ウインドウハンドル\r
896 *               RECT *Rect : RECT\r
897 *\r
898 *       Return Value\r
899 *               なし\r
900 *----------------------------------------------------------------------------*/\r
901 \r
902 void RectClientToScreen(HWND hWnd, RECT *Rect)\r
903 {\r
904         POINT Tmp;\r
905 \r
906         Tmp.x = Rect->left;\r
907         Tmp.y = Rect->top;\r
908         ClientToScreen(hWnd, &Tmp);\r
909         Rect->left = Tmp.x;\r
910         Rect->top = Tmp.y;\r
911 \r
912         Tmp.x = Rect->right;\r
913         Tmp.y = Rect->bottom;\r
914         ClientToScreen(hWnd, &Tmp);\r
915         Rect->right = Tmp.x;\r
916         Rect->bottom = Tmp.y;\r
917 \r
918         return;\r
919 }\r
920 \r
921 \r
922 /*----- 16進文字をバイナリに変換 ----------------------------------------------\r
923 *\r
924 *       Parameter\r
925 *               char Ch : 16進文字\r
926 *\r
927 *       Return Value\r
928 *               int バイナリ値\r
929 *----------------------------------------------------------------------------*/\r
930 \r
931 int hex2bin(char Ch)\r
932 {\r
933         int Ret;\r
934 \r
935         if((Ch >= '0') && (Ch <= '9'))\r
936                 Ret = Ch - '0';\r
937         else if((Ch >= 'A') && (Ch <= 'F'))\r
938                 Ret = Ch - 'A' + 10;\r
939         else if((Ch >= 'a') && (Ch <= 'f'))\r
940                 Ret = Ch - 'a' + 10;\r
941 \r
942         return(Ret);\r
943 }\r
944 \r
945 \r
946 /*----- UNC文字列を分解する ------------------------------------------------\r
947 *\r
948 *       Parameter\r
949 *               char *unc : UNC文字列\r
950 *               char *Host : ホスト名をコピーするバッファ (サイズは HOST_ADRS_LEN+1)\r
951 *               char *Path : パス名をコピーするバッファ (サイズは FMAX_PATH+1)\r
952 *               char *File : ファイル名をコピーするバッファ (サイズは FMAX_PATH+1)\r
953 *               char *User : ユーザ名をコピーするバッファ (サイズは USER_NAME_LEN+1)\r
954 *               char *Pass : パスワードをコピーするバッファ (サイズは PASSWORD_LEN+1)\r
955 *               int *Port : ポート番号をコピーするバッファ\r
956 *\r
957 *       Return Value\r
958 *               int ステータス\r
959 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
960 *\r
961 *       "\"は全て"/"に置き換える\r
962 *----------------------------------------------------------------------------*/\r
963 \r
964 int SplitUNCpath(char *unc, char *Host, char *Path, char *File, char *User, char *Pass, int *Port)\r
965 {\r
966         int Sts;\r
967         char *Pos1;\r
968         char *Pos2;\r
969         char Tmp[FMAX_PATH+1];\r
970 \r
971         memset(Host, NUL, HOST_ADRS_LEN+1);\r
972         memset(Path, NUL, FMAX_PATH+1);\r
973         memset(File, NUL, FMAX_PATH+1);\r
974         memset(User, NUL, USER_NAME_LEN+1);\r
975         memset(Pass, NUL, PASSWORD_LEN+1);\r
976         *Port = PORT_NOR;\r
977 \r
978         ReplaceAll(unc, '\\', '/');\r
979 \r
980         if((Pos1 = _mbsstr(unc, "//")) != NULL)\r
981                 Pos1 += 2;\r
982         else\r
983                 Pos1 = unc;\r
984 \r
985         if((Pos2 = _mbschr(Pos1, '@')) != NULL)\r
986         {\r
987                 memset(Tmp, NUL, FMAX_PATH+1);\r
988                 memcpy(Tmp, Pos1, Pos2-Pos1);\r
989                 Pos1 = Pos2 + 1;\r
990 \r
991                 if((Pos2 = _mbschr(Tmp, ':')) != NULL)\r
992                 {\r
993                         memcpy(User, Tmp, min1(Pos2-Tmp, USER_NAME_LEN));\r
994                         strncpy(Pass, Pos2+1, PASSWORD_LEN);\r
995                 }\r
996                 else\r
997                         strncpy(User, Tmp, USER_NAME_LEN);\r
998         }\r
999 \r
1000         // IPv6対応\r
1001         if((Pos2 = _mbschr(Pos1, '[')) != NULL && Pos2 < _mbschr(Pos1, ':'))\r
1002         {\r
1003                 Pos1 = Pos2 + 1;\r
1004                 if((Pos2 = _mbschr(Pos2, ']')) != NULL)\r
1005                 {\r
1006                         memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1007                         Pos1 = Pos2 + 1;\r
1008                 }\r
1009         }\r
1010 \r
1011         if((Pos2 = _mbschr(Pos1, ':')) != NULL)\r
1012         {\r
1013                 // IPv6対応\r
1014 //              memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1015                 if(strlen(Host) == 0)\r
1016                         memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1017                 Pos2++;\r
1018                 if(IsDigit(*Pos2))\r
1019                 {\r
1020                         *Port = atoi(Pos2);\r
1021                         while(*Pos2 != NUL)\r
1022                         {\r
1023                                 if(IsDigit(*Pos2) == 0)\r
1024                                         break;\r
1025                                 Pos2++;\r
1026                         }\r
1027                 }\r
1028                 RemoveFileName(Pos2, Path);\r
1029                 strncpy(File, GetFileName(Pos2), FMAX_PATH);\r
1030         }\r
1031         else if((Pos2 = _mbschr(Pos1, '/')) != NULL)\r
1032         {\r
1033                 // IPv6対応\r
1034 //              memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1035                 if(strlen(Host) == 0)\r
1036                         memcpy(Host, Pos1, min1(Pos2-Pos1, HOST_ADRS_LEN));\r
1037                 RemoveFileName(Pos2, Path);\r
1038                 strncpy(File, GetFileName(Pos2), FMAX_PATH);\r
1039         }\r
1040         else\r
1041         {\r
1042                 // IPv6対応\r
1043 //              strncpy(Host, Pos1, HOST_ADRS_LEN);\r
1044                 if(strlen(Host) == 0)\r
1045                         strncpy(Host, Pos1, HOST_ADRS_LEN);\r
1046         }\r
1047 \r
1048         Sts = FFFTP_FAIL;\r
1049         if(strlen(Host) > 0)\r
1050                 Sts = FFFTP_SUCCESS;\r
1051 \r
1052         return(Sts);\r
1053 }\r
1054 \r
1055 \r
1056 /*----- 日付文字列(JST)をFILETIME(UTC)に変換 ----------------------------------\r
1057 *\r
1058 *       Parameter\r
1059 *               char *Time : 日付文字列 ("yyyy/mm/dd hh:mm")\r
1060 *               FILETIME *Buf : ファイルタイムを返すワーク\r
1061 *\r
1062 *       Return Value\r
1063 *               int ステータス\r
1064 *                       YES/NO=日付情報がなかった\r
1065 *----------------------------------------------------------------------------*/\r
1066 \r
1067 int TimeString2FileTime(char *Time, FILETIME *Buf)\r
1068 {\r
1069         SYSTEMTIME sTime;\r
1070         FILETIME fTime;\r
1071         int Ret;\r
1072 \r
1073         Ret = NO;\r
1074     Buf->dwLowDateTime = 0;\r
1075     Buf->dwHighDateTime = 0;\r
1076 \r
1077         if(strlen(Time) >= 16)\r
1078         {\r
1079                 if(IsDigit(Time[0]) && IsDigit(Time[5]) && IsDigit(Time[8]) && \r
1080                    IsDigit(Time[12]) && IsDigit(Time[14]))\r
1081                 {\r
1082                         Ret = YES;\r
1083                 }\r
1084 \r
1085                 sTime.wYear = atoi(Time);\r
1086                 sTime.wMonth = atoi(Time + 5);\r
1087                 sTime.wDay = atoi(Time + 8);\r
1088                 if(Time[11] != ' ')\r
1089                         sTime.wHour = atoi(Time + 11);\r
1090                 else\r
1091                         sTime.wHour = atoi(Time + 12);\r
1092                 sTime.wMinute = atoi(Time + 14);\r
1093                 sTime.wSecond = 0;\r
1094                 sTime.wMilliseconds = 0;\r
1095 \r
1096                 SystemTimeToFileTime(&sTime, &fTime);\r
1097                 LocalFileTimeToFileTime(&fTime, Buf);\r
1098         }\r
1099         return(Ret);\r
1100 }\r
1101 \r
1102 \r
1103 /*----- FILETIME(UTC)を日付文字列(JST)に変換 ----------------------------------\r
1104 *\r
1105 *       Parameter\r
1106 *               FILETIME *Time : ファイルタイム\r
1107 *               char *Buf : 日付文字列を返すワーク\r
1108 *               int Mode : モード (DISPFORM_xxx)\r
1109 *               int InfoExist : 情報があるかどうか (FINFO_xxx)\r
1110 *\r
1111 *       Return Value\r
1112 *               なし\r
1113 *----------------------------------------------------------------------------*/\r
1114 \r
1115 void FileTime2TimeString(FILETIME *Time, char *Buf, int Mode, int InfoExist)\r
1116 {\r
1117         SYSTEMTIME sTime;\r
1118         FILETIME fTime;\r
1119 \r
1120         if(Mode == DISPFORM_LEGACY)\r
1121         {\r
1122                 if((Time->dwLowDateTime == 0) && (Time->dwHighDateTime == 0))\r
1123                         InfoExist = 0;\r
1124 \r
1125                 /* "yyyy/mm/dd hh:mm" */\r
1126                 FileTimeToLocalFileTime(Time, &fTime);\r
1127                 FileTimeToSystemTime(&fTime, &sTime);\r
1128 \r
1129                 if(InfoExist & FINFO_DATE)\r
1130                         sprintf(Buf, "%04d/%02d/%02d ", sTime.wYear, sTime.wMonth, sTime.wDay);\r
1131                 else\r
1132                         sprintf(Buf, "           ");\r
1133 \r
1134                 if(InfoExist & FINFO_TIME)\r
1135                         sprintf(Buf+11, "%2d:%02d", sTime.wHour, sTime.wMinute);\r
1136                 else\r
1137                         sprintf(Buf+11, "     ");\r
1138         }\r
1139         else\r
1140         {\r
1141 //              if (!strftime((char *)str, 100, "%c",  (const struct tm *)thetime))\r
1142 //                      SetTaskMsg("strftime が失敗しました!\n");\r
1143         }\r
1144         return;\r
1145 }\r
1146 \r
1147 \r
1148 /*----- ファイルタイムを指定タイムゾーンのローカルタイムからGMTに変換 ---------\r
1149 *\r
1150 *       Parameter\r
1151 *               FILETIME *Time : ファイルタイム\r
1152 *               int TimeZone : タイムゾーン\r
1153 *\r
1154 *       Return Value\r
1155 *               なし\r
1156 *----------------------------------------------------------------------------*/\r
1157 \r
1158 void SpecificLocalFileTime2FileTime(FILETIME *Time, int TimeZone)\r
1159 {\r
1160         unsigned __int64 Tmp64;\r
1161 \r
1162         Tmp64 = (unsigned __int64)Time->dwLowDateTime +\r
1163                         ((unsigned __int64)Time->dwHighDateTime << 32);\r
1164 \r
1165         Tmp64 -= (__int64)TimeZone * (__int64)36000000000;\r
1166 \r
1167         Time->dwHighDateTime = (DWORD)(Tmp64 >> 32);\r
1168         Time->dwLowDateTime = (DWORD)(Tmp64 & 0xFFFFFFFF);\r
1169 \r
1170         return;\r
1171 }\r
1172 \r
1173 \r
1174 /*----- 属性文字列を値に変換 --------------------------------------------------\r
1175 *\r
1176 *       Parameter\r
1177 *               char *Str : 属性文字列 ("rwxrwxrwx")\r
1178 *\r
1179 *       Return Value\r
1180 *               int 値\r
1181 *----------------------------------------------------------------------------*/\r
1182 \r
1183 int AttrString2Value(char *Str)\r
1184 {\r
1185         int Ret;\r
1186         char Tmp[10];\r
1187 \r
1188         Ret = 0;\r
1189         memset(Tmp, 0, 10);\r
1190         strncpy(Tmp, Str, 9);\r
1191 \r
1192         if(Tmp[0] != '-')\r
1193                 Ret |= 0x400;\r
1194         if(Tmp[1] != '-')\r
1195                 Ret |= 0x200;\r
1196         if(Tmp[2] != '-')\r
1197                 Ret |= 0x100;\r
1198 \r
1199         if(Tmp[3] != '-')\r
1200                 Ret |= 0x40;\r
1201         if(Tmp[4] != '-')\r
1202                 Ret |= 0x20;\r
1203         if(Tmp[5] != '-')\r
1204                 Ret |= 0x10;\r
1205 \r
1206         if(Tmp[6] != '-')\r
1207                 Ret |= 0x4;\r
1208         if(Tmp[7] != '-')\r
1209                 Ret |= 0x2;\r
1210         if(Tmp[8] != '-')\r
1211                 Ret |= 0x1;\r
1212 \r
1213         return(Ret);\r
1214 }\r
1215 \r
1216 \r
1217 /*----- 属性の値を文字列に変換 ------------------------------------------------\r
1218 *\r
1219 *       Parameter\r
1220 *               int Attr : 属性の値\r
1221 *               char *Buf : 属性文字列をセットするバッファ ("rwxrwxrwx")\r
1222 *\r
1223 *       Return Value\r
1224 *               int 値\r
1225 *----------------------------------------------------------------------------*/\r
1226 \r
1227 void AttrValue2String(int Attr, char *Buf)\r
1228 {\r
1229         strcpy(Buf, "---------");\r
1230 \r
1231         if(Attr & 0x400)\r
1232                 Buf[0] = 'r';\r
1233         if(Attr & 0x200)\r
1234                 Buf[1] = 'w';\r
1235         if(Attr & 0x100)\r
1236                 Buf[2] = 'x';\r
1237 \r
1238         if(Attr & 0x40)\r
1239                 Buf[3] = 'r';\r
1240         if(Attr & 0x20)\r
1241                 Buf[4] = 'w';\r
1242         if(Attr & 0x10)\r
1243                 Buf[5] = 'x';\r
1244 \r
1245         if(Attr & 0x4)\r
1246                 Buf[6] = 'r';\r
1247         if(Attr & 0x2)\r
1248                 Buf[7] = 'w';\r
1249         if(Attr & 0x1)\r
1250                 Buf[8] = 'x';\r
1251 \r
1252         return;\r
1253 }\r
1254 \r
1255 \r
1256 /*----- INIファイル文字列を整形 -----------------------------------------------\r
1257 *\r
1258 *       Parameter\r
1259 *               char *Str : 文字列\r
1260 *\r
1261 *       Return Value\r
1262 *               なし\r
1263 *----------------------------------------------------------------------------*/\r
1264 \r
1265 void FormatIniString(char *Str)\r
1266 {\r
1267         char *Put;\r
1268 \r
1269         Put = Str;\r
1270         while(*Str != NUL)\r
1271         {\r
1272                 if((*Str != ' ') && (*Str != '\t') && (*Str != '\n'))\r
1273                         *Put++ = *Str;\r
1274                 if(*Str++ == '=')\r
1275                         break;\r
1276         }\r
1277 \r
1278         while(*Str != NUL)\r
1279         {\r
1280                 if((*Str != 0x22) && (*Str != '\n'))\r
1281                         *Put++ = *Str;\r
1282                 Str++;\r
1283         }\r
1284         *Put = NUL;\r
1285 \r
1286         return;\r
1287 }\r
1288 \r
1289 \r
1290 /*----- ファイル選択 ----------------------------------------------------------\r
1291 *\r
1292 *       Parameter\r
1293 *               HWND hWnd : ウインドウハンドル\r
1294 *               char *Fname : ファイル名を返すバッファ\r
1295 *               char *Title : タイトル\r
1296 *               char *Filters : フィルター文字列\r
1297 *               char *Ext : デフォルト拡張子\r
1298 *               int Flags : 追加するフラグ\r
1299 *               int Save : 「開く」か「保存」か (0=開く, 1=保存)\r
1300 *\r
1301 *       Return Value\r
1302 *               int ステータス\r
1303 *                       TRUE/FALSE=取消\r
1304 *----------------------------------------------------------------------------*/\r
1305 \r
1306 int SelectFile(HWND hWnd, char *Fname, char *Title, char *Filters, char *Ext, int Flags, int Save)\r
1307 {\r
1308         OPENFILENAME OpenFile;\r
1309         char Tmp[FMAX_PATH+1];\r
1310         char Cur[FMAX_PATH+1];\r
1311         int Sts;\r
1312 \r
1313         GetCurrentDirectory(FMAX_PATH, Cur);\r
1314 \r
1315         strcpy(Tmp, Fname);\r
1316         OpenFile.lStructSize = sizeof(OPENFILENAME);\r
1317         OpenFile.hwndOwner = hWnd;\r
1318         OpenFile.hInstance = 0;\r
1319         OpenFile.lpstrFilter = Filters;\r
1320         OpenFile.lpstrCustomFilter = NULL;\r
1321         OpenFile.nFilterIndex = 1;\r
1322         OpenFile.lpstrFile = Tmp;\r
1323         OpenFile.nMaxFile = FMAX_PATH;\r
1324         OpenFile.lpstrFileTitle = NULL;\r
1325         OpenFile.nMaxFileTitle = 0;\r
1326         OpenFile.lpstrInitialDir = NULL;\r
1327         OpenFile.lpstrTitle = Title;\r
1328         OpenFile.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | Flags;\r
1329         OpenFile.nFileOffset = 0;\r
1330         OpenFile.nFileExtension = 0;\r
1331         OpenFile.lpstrDefExt = Ext;\r
1332         OpenFile.lCustData = 0;\r
1333         OpenFile.lpfnHook = NULL;\r
1334         OpenFile.lpTemplateName = NULL;\r
1335 \r
1336         if(Save == 0)\r
1337         {\r
1338                 if((Sts = GetOpenFileName(&OpenFile)) == TRUE)\r
1339                         strcpy(Fname,Tmp);\r
1340         }\r
1341         else\r
1342         {\r
1343                 if((Sts = GetSaveFileName(&OpenFile)) == TRUE)\r
1344                         strcpy(Fname,Tmp);\r
1345         }\r
1346         SetCurrentDirectory(Cur);\r
1347         return(Sts);\r
1348 }\r
1349 \r
1350 \r
1351 /*----- ディレクトリを選択 ----------------------------------------------------\r
1352 *\r
1353 *       Parameter\r
1354 *               HWND hWnd : ウインドウハンドル\r
1355 *               char *Buf : ディレクトリ名を返すバッファ(初期ディレクトリ名)\r
1356 *               int MaxLen : バッファのサイズ\r
1357 *\r
1358 *       Return Value\r
1359 *               int ステータス\r
1360 *                       TRUE/FALSE=取消\r
1361 *----------------------------------------------------------------------------*/\r
1362 \r
1363 int SelectDir(HWND hWnd, char *Buf, int MaxLen)\r
1364 {\r
1365         char Tmp[FMAX_PATH+1];\r
1366         char Cur[FMAX_PATH+1];\r
1367         BROWSEINFO  Binfo;\r
1368         LPITEMIDLIST lpIdll;\r
1369         int Sts;\r
1370         LPMALLOC lpMalloc;\r
1371 \r
1372         Sts = FALSE;\r
1373         GetCurrentDirectory(FMAX_PATH, Cur);\r
1374 \r
1375         if(SHGetMalloc(&lpMalloc) == NOERROR)\r
1376         {\r
1377                 Binfo.hwndOwner = hWnd;\r
1378                 Binfo.pidlRoot = NULL;\r
1379                 Binfo.pszDisplayName = Tmp;\r
1380                 Binfo.lpszTitle = MSGJPN185;\r
1381                 Binfo.ulFlags = BIF_RETURNONLYFSDIRS;\r
1382                 Binfo.lpfn = NULL;\r
1383                 Binfo.lParam = 0;\r
1384                 Binfo.iImage = 0;\r
1385                 if((lpIdll = SHBrowseForFolder(&Binfo)) != NULL)\r
1386                 {\r
1387                         SHGetPathFromIDList(lpIdll, Tmp);\r
1388                         memset(Buf, NUL, MaxLen);\r
1389                         strncpy(Buf, Tmp, MaxLen-1);\r
1390                         Sts = TRUE;\r
1391                         lpMalloc->lpVtbl->Free(lpMalloc, lpIdll);\r
1392             }\r
1393             lpMalloc->lpVtbl->Release(lpMalloc);\r
1394                 SetCurrentDirectory(Cur);\r
1395         }\r
1396         return(Sts);\r
1397 }\r
1398 \r
1399 \r
1400 /*----- 値に関連付けられたラジオボタンをチェックする --------------------------\r
1401 *\r
1402 *       Parameter\r
1403 *               HWND hDlg : ダイアログボックスのウインドウハンドル\r
1404 *               int Value : 値\r
1405 *               const RADIOBUTTON *Buttons : ラジオボタンと値の関連付けテーブル\r
1406 *               int Num : ボタンの数\r
1407 *\r
1408 *       Return Value\r
1409 *               なし\r
1410 *\r
1411 *       Note\r
1412 *               値に関連付けられたボタンが無い時は、テーブルの最初に登録されているボタ\r
1413 *               ンをチェックする\r
1414 *----------------------------------------------------------------------------*/\r
1415 \r
1416 void SetRadioButtonByValue(HWND hDlg, int Value, const RADIOBUTTON *Buttons, int Num)\r
1417 {\r
1418         int i;\r
1419         int Def;\r
1420 \r
1421         Def = Buttons->ButID;\r
1422         for(i = 0; i < Num; i++)\r
1423         {\r
1424                 if(Value == Buttons->Value)\r
1425                 {\r
1426                         SendDlgItemMessage(hDlg, Buttons->ButID, BM_SETCHECK, 1, 0);\r
1427                         /* ラジオボタンを変更した時に他の項目のハイドなどを行なう事が      */\r
1428                         /* あるので、そのために WM_COMMAND を送る                                          */\r
1429                         SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(Buttons->ButID, 0), 0);\r
1430                         break;\r
1431                 }\r
1432                 Buttons++;\r
1433         }\r
1434         if(i == Num)\r
1435         {\r
1436                 SendDlgItemMessage(hDlg, Def, BM_SETCHECK, 1, 0);\r
1437                 SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(Def, 0), 0);\r
1438         }\r
1439         return;\r
1440 }\r
1441 \r
1442 \r
1443 /*----- チェックされているボタンに関連付けられた値を返す ----------------------\r
1444 *\r
1445 *       Parameter\r
1446 *               HWND hDlg : ダイアログボックスのウインドウハンドル\r
1447 *               const RADIOBUTTON *Buttons : ラジオボタンと値の関連付けテーブル\r
1448 *               int Num : ボタンの数\r
1449 *\r
1450 *       Return Value\r
1451 *               int 値\r
1452 *\r
1453 *       Note\r
1454 *               どのボタンもチェックされていない時は、テーブルの最初に登録されているボ\r
1455 *               タンの値を返す\r
1456 *----------------------------------------------------------------------------*/\r
1457 \r
1458 int AskRadioButtonValue(HWND hDlg, const RADIOBUTTON *Buttons, int Num)\r
1459 {\r
1460         int i;\r
1461         int Ret;\r
1462 \r
1463         Ret = Buttons->Value;\r
1464         for(i = 0; i < Num; i++)\r
1465         {\r
1466                 if(SendDlgItemMessage(hDlg, Buttons->ButID, BM_GETCHECK, 0, 0) == 1)\r
1467                 {\r
1468                         Ret = Buttons->Value;\r
1469                         break;\r
1470                 }\r
1471                 Buttons++;\r
1472         }\r
1473         return(Ret);\r
1474 }\r
1475 \r
1476 \r
1477 /*----- 16進文字列を数値に変換 ----------------------------------------------\r
1478 *\r
1479 *       Parameter\r
1480 *               char *Str : 文字列\r
1481 *\r
1482 *       Return Value\r
1483 *               int 値\r
1484 *----------------------------------------------------------------------------*/\r
1485 \r
1486 int xtoi(char *Str)\r
1487 {\r
1488         int Ret;\r
1489 \r
1490         Ret = 0;\r
1491         while(*Str != NUL)\r
1492         {\r
1493                 Ret *= 0x10;\r
1494                 if((*Str >= '0') && (*Str <= '9'))\r
1495                         Ret += *Str - '0';\r
1496                 else if((*Str >= 'A') && (*Str <= 'F'))\r
1497                         Ret += *Str - 'A' + 10;\r
1498                 else if((*Str >= 'a') && (*Str <= 'f'))\r
1499                         Ret += *Str - 'a' + 10;\r
1500                 else\r
1501                         break;\r
1502 \r
1503                 Str++;\r
1504         }\r
1505         return(Ret);\r
1506 }\r
1507 \r
1508 \r
1509 /*----- ファイルが読み取り可能かどうかを返す ----------------------------------\r
1510 *\r
1511 *       Parameter\r
1512 *               char *Fname : ファイル名\r
1513 *\r
1514 *       Return Value\r
1515 *               int ステータス\r
1516 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1517 *----------------------------------------------------------------------------*/\r
1518 \r
1519 int CheckFileReadable(char *Fname)\r
1520 {\r
1521         int Sts;\r
1522         HANDLE iFileHandle;\r
1523         SECURITY_ATTRIBUTES Sec;\r
1524 \r
1525         Sts = FFFTP_FAIL;\r
1526 \r
1527         Sec.nLength = sizeof(SECURITY_ATTRIBUTES);\r
1528         Sec.lpSecurityDescriptor = NULL;\r
1529         Sec.bInheritHandle = FALSE;\r
1530 \r
1531         if((iFileHandle = CreateFile(Fname, GENERIC_READ,\r
1532                 FILE_SHARE_READ|FILE_SHARE_WRITE, &Sec, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)\r
1533         {\r
1534                 Sts = FFFTP_SUCCESS;\r
1535                 CloseHandle(iFileHandle);\r
1536         }\r
1537         return(Sts);\r
1538 }\r
1539 \r
1540 \r
1541 \r
1542 \r
1543 \r
1544 int max1(int n, int m)\r
1545 {\r
1546         if(n > m)\r
1547                 return(n);\r
1548         else\r
1549                 return(m);\r
1550 }\r
1551 \r
1552 \r
1553 \r
1554 int min1(int n, int m)\r
1555 {\r
1556         if(n < m)\r
1557                 return(n);\r
1558         else\r
1559                 return(m);\r
1560 }\r
1561 \r
1562 \r
1563 void ExcEndianDWORD(DWORD *x)\r
1564 {\r
1565         BYTE *Pos;\r
1566         BYTE Tmp;\r
1567 \r
1568         Pos = (BYTE *)x;\r
1569         Tmp = *(Pos + 0);\r
1570         *(Pos + 0) = *(Pos + 3);\r
1571         *(Pos + 3) = Tmp;\r
1572         Tmp = *(Pos + 1);\r
1573         *(Pos + 1) = *(Pos + 2);\r
1574         *(Pos + 2) = Tmp;\r
1575         return;\r
1576 }\r
1577 \r
1578 \r
1579 \r
1580 \r
1581 /*----- int値の入れ替え -------------------------------------------------------\r
1582 *\r
1583 *       Parameter\r
1584 *               int *Num1 : 数値1\r
1585 *               int *Num2 : 数値2\r
1586 *\r
1587 *       Return Value\r
1588 *               なし\r
1589 *----------------------------------------------------------------------------*/\r
1590 \r
1591 void SwapInt(int *Num1, int *Num2)\r
1592 {\r
1593         int Tmp;\r
1594 \r
1595         Tmp = *Num1;\r
1596         *Num1 = *Num2;\r
1597         *Num2 = Tmp;\r
1598         return;\r
1599 }\r
1600 \r
1601 \r
1602 /*----- 指定されたフォルダがあるかどうかチェック -------------------------------\r
1603 *\r
1604 *       Parameter\r
1605 *               char *Path : パス\r
1606 *\r
1607 *       Return Value\r
1608 *               int ステータス (YES/NO)\r
1609 *----------------------------------------------------------------------------*/\r
1610 \r
1611 int IsFolderExist(char *Path)\r
1612 {\r
1613         int Sts;\r
1614         char Tmp[FMAX_PATH+1];\r
1615         DWORD Attr;\r
1616 \r
1617         Sts = YES;\r
1618         if(strlen(Path) > 0)\r
1619         {\r
1620                 strcpy(Tmp, Path);\r
1621                 if(_mbscmp(Tmp+1, ":\\") != 0)\r
1622                         RemoveYenTail(Tmp);\r
1623 \r
1624                 Attr = GetFileAttributes(Tmp);\r
1625                 if((Attr == 0xFFFFFFFF) || ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0))\r
1626                         Sts = NO;\r
1627         }\r
1628         return(Sts);\r
1629 }\r
1630 \r
1631 \r
1632 /*----- テーブルにしたがって数値を登録 -----------------------------------------\r
1633 *\r
1634 *       Parameter\r
1635 *               int x : 数値\r
1636 *               int Dir : 変換方向\r
1637 *               INTCONVTBL *Tbl : テーブル\r
1638 *               int Num : テーブルの数値の数\r
1639 *\r
1640 *       Return Value\r
1641 *               int 数値\r
1642 *----------------------------------------------------------------------------*/\r
1643 \r
1644 int ConvertNum(int x, int Dir, const INTCONVTBL *Tbl, int Num)\r
1645 {\r
1646         int i;\r
1647         int Ret;\r
1648 \r
1649         Ret = x;\r
1650         for(i = 0; i < Num; i++)\r
1651         {\r
1652                 if((Dir == 0) && (Tbl->Num1 == x))\r
1653                 {\r
1654                         Ret = Tbl->Num2;\r
1655                         break;\r
1656                 }\r
1657                 else if((Dir == 1) && (Tbl->Num2 == x))\r
1658                 {\r
1659                         Ret = Tbl->Num1;\r
1660                         break;\r
1661                 }\r
1662                 Tbl++;\r
1663         }\r
1664         return(Ret);\r
1665 }\r
1666 \r
1667 \r
1668 \r
1669 \r
1670 \r
1671 \r
1672 /*----- ファイルをゴミ箱に削除 ------------------------------------------------\r
1673 *\r
1674 *       Parameter\r
1675 *               char *Path : ファイル名\r
1676 *\r
1677 *       Return Value\r
1678 *               int ステータス (0=正常終了)\r
1679 *----------------------------------------------------------------------------*/\r
1680 \r
1681 int MoveFileToTrashCan(char *Path)\r
1682 {\r
1683         SHFILEOPSTRUCT FileOp;\r
1684         char Tmp[FMAX_PATH+2];\r
1685 \r
1686         memset(Tmp, 0, FMAX_PATH+2);\r
1687         strcpy(Tmp, Path);\r
1688         FileOp.hwnd = NULL;\r
1689         FileOp.wFunc = FO_DELETE;\r
1690         FileOp.pFrom = Tmp;\r
1691         FileOp.pTo = "";\r
1692         FileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO;\r
1693         FileOp.lpszProgressTitle = "";\r
1694         return(SHFileOperation(&FileOp));\r
1695 }\r
1696 \r
1697 \r
1698 \r
1699 \r
1700 LONGLONG MakeLongLong(DWORD High, DWORD Low)\r
1701 {\r
1702         LONGLONG z;\r
1703         LONGLONG x1, y1;\r
1704 \r
1705         x1 = (LONGLONG)Low;\r
1706         y1 = (LONGLONG)High;\r
1707         z = x1 | (y1 << 32);\r
1708         return(z);\r
1709 }\r
1710 \r
1711 \r
1712 char *MakeNumString(LONGLONG Num, char *Buf, BOOL Comma)\r
1713 {\r
1714         int i;\r
1715         char *Pos;\r
1716 \r
1717         Pos = Buf;\r
1718         *Pos = '\0';\r
1719 \r
1720         i = 1;\r
1721         do\r
1722         {\r
1723                 *Pos++ = (char)(Num % 10) + '0';\r
1724                 Num /= 10;\r
1725                 if((Comma == TRUE) && ((i % 3) == 0) && (Num != 0))\r
1726                         *Pos++ = ',';\r
1727                 i++;\r
1728         }\r
1729         while(Num != 0);\r
1730         *Pos = NUL;\r
1731         _strrev(Buf);\r
1732 \r
1733         return(Buf);\r
1734 }\r
1735 \r
1736 \r
1737 // 異なるファイルが表示されるバグ修正\r
1738 \r
1739 // ShellExecute等で使用されるファイル名を修正\r
1740 // UNCでない場合に末尾の半角スペースは無視されるため拡張子が補完されなくなるまで半角スペースを追加\r
1741 // 現在UNC対応の予定は無い\r
1742 char* MakeDistinguishableFileName(char* Out, char* In)\r
1743 {\r
1744         char* Fname;\r
1745         char Tmp[FMAX_PATH+1];\r
1746         char Tmp2[FMAX_PATH+3];\r
1747         HANDLE hFind;\r
1748         WIN32_FIND_DATA Find;\r
1749         if(strlen(GetFileExt(GetFileName(In))) > 0)\r
1750                 strcpy(Out, In);\r
1751         else\r
1752         {\r
1753                 Fname = GetFileName(In);\r
1754                 strcpy(Tmp, In);\r
1755                 strcpy(Tmp2, Tmp);\r
1756                 strcat(Tmp2, ".*");\r
1757                 while(strlen(Tmp) < FMAX_PATH && (hFind = FindFirstFile(Tmp2, &Find)) != INVALID_HANDLE_VALUE)\r
1758                 {\r
1759                         do\r
1760                         {\r
1761                                 if(strcmp(Find.cFileName, Fname) != 0)\r
1762                                         break;\r
1763                         }\r
1764                         while(FindNextFile(hFind, &Find));\r
1765                         FindClose(hFind);\r
1766                         if(strcmp(Find.cFileName, Fname) != 0)\r
1767                         {\r
1768                                 strcat(Tmp, " ");\r
1769                                 strcpy(Tmp2, Tmp);\r
1770                                 strcat(Tmp2, ".*");\r
1771                         }\r
1772                         else\r
1773                                 break;\r
1774                 }\r
1775                 strcpy(Out, Tmp);\r
1776         }\r
1777         return Out;\r
1778 }\r
1779 \r