OSDN Git Service

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