1 /*$
2 Copyright (C) 2013-2020 Azel.
3
4 This file is part of AzPainter.
5
6 AzPainter is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 AzPainter is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 $*/
19
20 /*****************************************
21 * MainWindow
22 *
23 * ファイル関連コマンド
24 *****************************************/
25
26 #include <string.h>
27
28 #include "mDef.h"
29 #include "mStr.h"
30 #include "mUtilFile.h"
31 #include "mMenu.h"
32 #include "mIconButtons.h"
33 #include "mMessageBox.h"
34 #include "mSysDialog.h"
35 #include "mTrans.h"
36
37 #include "defMacros.h"
38 #include "defDraw.h"
39 #include "defConfig.h"
40 #include "defMainWindow.h"
41 #include "defFileFormat.h"
42 #include "AppErr.h"
43
44 #define LOADERR_DEFINE
45 #include "defLoadErr.h"
46
47 #include "defMainWindow.h"
48 #include "MainWindow.h"
49 #include "MainWindow_pv.h"
50 #include "FileDialog.h"
51 #include "PopupThread.h"
52 #include "Undo.h"
53
54 #include "draw_main.h"
55 #include "draw_file.h"
56
57 #include "trgroup.h"
58 #include "trid_mainmenu.h"
59 #include "trid_message.h"
60
61
62 //----------------------
63
64 mBool NewImageDialog_run(mWindow *owner,mSize *size,int *dpi,int *layertype);
65 mBool SaveOptionDlg_run(mWindow *owner,int format);
66
67 //----------------------
68
69
70
71 //============================
72 // FileFormat
73 //============================
74
75
76 /** ファイルのヘッダからフォーマット取得 */
77
FileFormat_getbyFileHeader(const char * filename)78 uint32_t FileFormat_getbyFileHeader(const char *filename)
79 {
80 uint8_t d[8],png[8] = {0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a};
81
82 if(mReadFileHead(filename, d, 8))
83 {
84 if(memcmp(d, "AZPDATA", 7) == 0)
85 {
86 //APD
87
88 if(d[7] < 2)
89 return FILEFORMAT_APD | FILEFORMAT_APD_v1v2;
90 else if(d[7] == 2)
91 return FILEFORMAT_APD | FILEFORMAT_APD_v3;
92 else
93 return FILEFORMAT_UNKNOWN;
94 }
95 else if(memcmp(d, "AZDWDAT", 7) == 0)
96 return FILEFORMAT_ADW;
97
98 else if(memcmp(d, "8BPS", 4) == 0)
99 return FILEFORMAT_PSD;
100
101 else if(memcmp(d, png, 8) == 0)
102 return FILEFORMAT_PNG;
103
104 else if(d[0] == 0xff && d[1] == 0xd8)
105 return FILEFORMAT_JPEG;
106
107 else if(d[0] == 'G' && d[1] == 'I' && d[2] == 'F')
108 return FILEFORMAT_GIF;
109
110 else if(d[0] == 'B' && d[1] == 'M')
111 return FILEFORMAT_BMP;
112 }
113
114 return FILEFORMAT_UNKNOWN;
115 }
116
117
118 //============================
119 // sub
120 //============================
121
122
123 /** 最近使ったファイルに追加 */
124
_add_recent_file(MainWindow * p,const char * filename)125 static void _add_recent_file(MainWindow *p,const char *filename)
126 {
127 mStrArrayAddRecent(APP_CONF->strRecentFile, CONFIG_RECENTFILE_NUM, filename, TRUE);
128
129 //メニュー
130
131 MainWindow_setRecentFileMenu(p);
132 }
133
134 /** ファイル履歴のメニューをセット */
135
MainWindow_setRecentFileMenu(MainWindow * p)136 void MainWindow_setRecentFileMenu(MainWindow *p)
137 {
138 mMenu *menu = p->menu_recentfile;
139
140 //削除
141
142 mMenuDeleteAll(menu);
143
144 //ファイル
145
146 mMenuSetStrArray(menu, MAINWINDOW_CMDID_RECENTFILE,
147 APP_CONF->strRecentFile, CONFIG_RECENTFILE_NUM);
148
149 //消去
150
151 if(!mStrIsEmpty(APP_CONF->strRecentFile))
152 {
153 mMenuAddSep(menu);
154
155 mMenuAddText_static(menu, TRMENU_FILE_RECENTFILE_CLEAR,
156 M_TR_T2(TRGROUP_MAINMENU, TRMENU_FILE_RECENTFILE_CLEAR));
157 }
158 }
159
160 /** ツールバーの開く/保存ドロップメニュー
161 *
162 * @return 選択された履歴の番号。-1 でキャンセル */
163
MainWindow_runMenu_toolbarDrop_opensave(MainWindow * p,mBool save)164 int MainWindow_runMenu_toolbarDrop_opensave(MainWindow *p,mBool save)
165 {
166 mMenu *menu;
167 mMenuItemInfo *mi;
168 mStr *str_array;
169 mBox box;
170 int no;
171
172 str_array = (save)? APP_CONF->strRecentSaveDir: APP_CONF->strRecentOpenDir;
173
174 //履歴が一つもない (先頭が空)
175
176 if(mStrIsEmpty(str_array)) return -1;
177
178 //メニュー
179
180 menu = mMenuNew();
181
182 mMenuSetStrArray(menu, 0, str_array, CONFIG_RECENTDIR_NUM);
183
184 mIconButtonsGetItemBox(M_ICONBUTTONS(p->toolbar),
185 (save)? TRMENU_FILE_SAVE_AS: TRMENU_FILE_OPEN, &box, TRUE);
186
187 mi = mMenuPopup(menu, NULL, box.x, box.y + box.h, 0);
188 no = (mi)? mi->id: -1;
189
190 mMenuDestroy(menu);
191
192 return no;
193 }
194
195 /** 複製保存のドロップメニュー
196 *
197 * @return 選択された履歴の番号。-1 でキャンセル */
198
MainWindow_runMenu_toolbarDrop_savedup(MainWindow * p)199 int MainWindow_runMenu_toolbarDrop_savedup(MainWindow *p)
200 {
201 mMenu *menu,*sub;
202 mMenuItemInfo *mi;
203 mBox box;
204 int no,i;
205 static const char *format_str[] = {
206 "APD (AzPainter)", "PSD (PhotoShop)", "PNG", "JPEG", "BMP"
207 };
208
209 M_TR_G(TRGROUP_DROPMENU_SAVEDUP);
210
211 //保存形式サブメニュー
212
213 sub = mMenuNew();
214
215 mMenuAddNormal(sub, 1000, M_TR_T(1), 0, MMENUITEM_F_RADIO);
216
217 for(i = 0; i < 5; i++)
218 mMenuAddNormal(sub, 1001 + i, format_str[i], 0, MMENUITEM_F_RADIO);
219
220 mMenuSetCheck(sub, 1000 + APP_CONF->savedup_type, 1);
221
222 //main
223
224 menu = mMenuNew();
225
226 mMenuAddSubmenu(menu, 100, M_TR_T(0), sub);
227 mMenuAddSep(menu);
228 mMenuAddStrArray(menu, 0, APP_CONF->strRecentSaveDir, CONFIG_RECENTDIR_NUM);
229
230 //
231
232 mIconButtonsGetItemBox(M_ICONBUTTONS(p->toolbar),
233 TRMENU_FILE_SAVE_DUP, &box, TRUE);
234
235 mi = mMenuPopup(menu, NULL, box.x, box.y + box.h, 0);
236 no = (mi)? mi->id: -1;
237
238 mMenuDestroy(menu);
239
240 //保存形式変更
241
242 if(no >= 1000)
243 {
244 APP_CONF->savedup_type = no - 1000;
245 return -1;
246 }
247
248 return no;
249 }
250
251 /** ツールバーのファイル履歴メニュー */
252
MainWindow_runMenu_toolbar_recentfile(MainWindow * p)253 void MainWindow_runMenu_toolbar_recentfile(MainWindow *p)
254 {
255 mBox box;
256
257 //履歴が一つもない (先頭が空)
258
259 if(mStrIsEmpty(APP_CONF->strRecentFile)) return;
260
261 //メニュー (COMMAND イベントを送る)
262
263 mIconButtonsGetItemBox(M_ICONBUTTONS(p->toolbar),
264 TRMENU_FILE_RECENTFILE, &box, TRUE);
265
266 mMenuPopup(p->menu_recentfile, M_WIDGET(p), box.x, box.y + box.h, 0);
267 }
268
269
270 //============================
271 // 新規作成
272 //============================
273
274
275 /** 新規作成 */
276
MainWindow_newImage(MainWindow * p)277 void MainWindow_newImage(MainWindow *p)
278 {
279 mSize size;
280 int dpi,type;
281
282 //ダイアログ
283
284 if(!NewImageDialog_run(M_WINDOW(p), &size, &dpi, &type))
285 return;
286
287 //保存確認
288
289 if(!MainWindow_confirmSave(p)) return;
290
291 //新規
292
293 if(!drawImage_new(APP_DRAW, size.w, size.h, dpi, type))
294 {
295 MainWindow_apperr(APPERR_ALLOC, NULL);
296
297 drawImage_new(APP_DRAW, 300, 300, dpi, type);
298 }
299
300 //更新
301
302 MainWindow_updateNewCanvas(p, "");
303 }
304
305
306 //============================
307 // ファイルを開く
308 //============================
309
310
311 typedef struct
312 {
313 const char *filename;
314 char *errmes; //確保されたエラー文字列
315 int loaderr, //LOADERR_*
316 loadopt; //開くダイアログ時のオプション
317 uint32_t format;
318 }_thread_openfileinfo;
319
320
321 /** 読み込みスレッド処理 */
322 /*
323 * 戻り値が APPERR_OK で成功。それ以外の場合エラー。
324 * loaderr に LOADERR_OK 以外をセットすると、定義されたエラー文字列表示。
325 */
326
_thread_load(mPopupProgress * prog,void * data)327 static int _thread_load(mPopupProgress *prog,void *data)
328 {
329 _thread_openfileinfo *p = (_thread_openfileinfo *)data;
330 uint32_t format;
331 int ret = APPERR_LOAD,loaderr = -100;
332
333 format = p->format;
334
335 if(format & FILEFORMAT_APD)
336 {
337 //APD
338
339 if(format & FILEFORMAT_APD_v3)
340 {
341 //ver 3
342 if(drawFile_load_apd_v3(APP_DRAW, p->filename, prog))
343 ret = APPERR_OK;
344 }
345 else
346 //ver 1,2
347 loaderr = drawFile_load_apd_v1v2(p->filename, prog);
348 }
349 else if(format & FILEFORMAT_ADW)
350 //ADW
351 loaderr = drawFile_load_adw(p->filename, prog);
352 else if(format & FILEFORMAT_PSD)
353 {
354 //PSD
355
356 if(drawFile_load_psd(APP_DRAW, p->filename, prog, &p->errmes))
357 ret= APPERR_OK;
358 }
359 else
360 {
361 //画像ファイル
362
363 ret = drawImage_loadFile(APP_DRAW, p->filename, p->format,
364 FILEDIALOG_LAYERIMAGE_IS_IGNORE_ALPHA(p->loadopt),
365 prog, &p->errmes);
366 }
367
368 //loaderr に戻り値がある場合、
369 //関数の戻り値と loaderr セット
370
371 if(loaderr != -100)
372 {
373 if(loaderr == LOADERR_OK)
374 ret = APPERR_OK;
375 else
376 {
377 p->loaderr = loaderr;
378 ret = APPERR_LOAD;
379 }
380 }
381
382 return ret;
383 }
384
385 /** ファイルを開く (ダイアログ)
386 *
387 * @param recentno ディレクトリ履歴番号 (0 で最新の履歴) */
388
MainWindow_openFile(MainWindow * p,int recentno)389 void MainWindow_openFile(MainWindow *p,int recentno)
390 {
391 mStr str = MSTR_INIT;
392 int ret;
393
394 //ファイル名
395
396 ret = FileDialog_openLayerImage(M_WINDOW(p),
397 "Image Files (ADW/APD/PSD/BMP/PNG/JPEG/GIF)\t*.adw;*.apd;*.psd;*.bmp;*.png;*.jpg;*.jpeg;*.gif\t"
398 "AzPainter File (*.apd)\t*.apd\t"
399 "All Files\t*",
400 APP_CONF->strRecentOpenDir[recentno].buf, &str);
401
402 if(ret == -1) return;
403
404 //保存確認後、読み込み
405
406 if(MainWindow_confirmSave(p))
407 MainWindow_loadImage(p, str.buf, ret);
408
409 mStrFree(&str);
410 }
411
412 /** 画像読み込み処理
413 *
414 * @param loadopt 開くダイアログからのオプション (0 でデフォルト) */
415
MainWindow_loadImage(MainWindow * p,const char * filename,int loadopt)416 mBool MainWindow_loadImage(MainWindow *p,const char *filename,int loadopt)
417 {
418 _thread_openfileinfo dat;
419 int err;
420 uint32_t format;
421
422 //ヘッダからフォーマット取得
423
424 format = FileFormat_getbyFileHeader(filename);
425
426 if(format == FILEFORMAT_UNKNOWN)
427 {
428 MainWindow_apperr(APPERR_UNSUPPORTED_FORMAT, NULL);
429 return FALSE;
430 }
431
432 //読み込み
433
434 dat.filename = filename;
435 dat.format = format;
436 dat.errmes = NULL;
437 dat.loaderr = LOADERR_OK;
438 dat.loadopt = loadopt;
439
440 err = PopupThread_run(&dat, _thread_load);
441 if(err == -1) return FALSE;
442
443 //結果
444
445 if(err == APPERR_OK)
446 {
447 //---- 成功
448
449 mStr str = MSTR_INIT;
450
451 //フォーマット
452
453 p->fileformat = format;
454
455 //ファイル履歴追加
456 /* filename が履歴内の文字列の場合があるので、以降
457 * ファイル名を参照する場合は、ファイル履歴の先頭を参照すること。 */
458
459 _add_recent_file(p, filename);
460
461 //ディレクトリ履歴
462
463 mStrPathGetDir(&str, APP_CONF->strRecentFile[0].buf);
464
465 mStrArrayAddRecent(APP_CONF->strRecentOpenDir, CONFIG_RECENTDIR_NUM, str.buf, TRUE);
466
467 mStrFree(&str);
468
469 //更新
470
471 MainWindow_updateNewCanvas(p, APP_CONF->strRecentFile[0].buf);
472
473 return TRUE;
474 }
475 else
476 {
477 //---- 失敗
478
479 //エラーメッセージ
480
481 if(dat.errmes)
482 {
483 MainWindow_apperr(err, dat.errmes);
484 mFree(dat.errmes);
485 }
486 else if(dat.loaderr != LOADERR_OK)
487 MainWindow_apperr(err, g_loaderr_str[dat.loaderr]);
488
489 /* レイヤが一つもなければ新規作成。
490 * カレントレイヤが指定されていなければ途中まで読み込まれた */
491
492 if(drawImage_onLoadError(APP_DRAW))
493 MainWindow_updateNewCanvas(p, filename);
494
495 return FALSE;
496 }
497 }
498
499
500 //============================
501 // ファイル保存 sub
502 //============================
503
504
505 enum
506 {
507 FILETYPE_APD,
508 FILETYPE_PSD,
509 FILETYPE_PNG,
510 FILETYPE_JPEG,
511 FILETYPE_BMP
512 };
513
514
515 /** フォーマットフラグからファイル名に拡張子セット */
516
_save_set_ext(mStr * str,uint32_t format)517 static void _save_set_ext(mStr *str,uint32_t format)
518 {
519 uint32_t flag[] = {
520 FILEFORMAT_APD, FILEFORMAT_PSD, FILEFORMAT_PNG,
521 FILEFORMAT_JPEG, FILEFORMAT_BMP, 0
522 };
523 const char *ext[] = {
524 "apd", "psd", "png", "jpg", "bmp"
525 };
526 int i;
527
528 for(i = 0; flag[i]; i++)
529 {
530 if(format & flag[i])
531 {
532 mStrPathSetExt(str, ext[i]);
533 break;
534 }
535 }
536 }
537
538 /** フォーマットフラグからファイルタイプ取得 */
539
_save_format_to_type(uint32_t format)540 static int _save_format_to_type(uint32_t format)
541 {
542 uint32_t flag[] = {
543 FILEFORMAT_APD, FILEFORMAT_PSD, FILEFORMAT_PNG,
544 FILEFORMAT_JPEG, FILEFORMAT_BMP, 0
545 };
546 int i;
547
548 for(i = 0; flag[i]; i++)
549 {
550 if(format & flag[i])
551 return i;
552 }
553
554 return FILETYPE_APD;
555 }
556
557 /** 上書き保存時のメッセージ
558 *
559 * @return [0]キャンセル [1]上書き保存 [2]別名保存 */
560
_save_message(MainWindow * p)561 static int _save_message(MainWindow *p)
562 {
563 uint32_t ret;
564
565 //ADW/GIF 形式での上書き保存は不可 => 別名保存
566
567 if(p->fileformat & (FILEFORMAT_ADW | FILEFORMAT_GIF))
568 return 2;
569
570 //APD 以外の場合、確認
571
572 if(!(p->fileformat & FILEFORMAT_APD)
573 && (APP_CONF->optflags & CONFIG_OPTF_MES_SAVE_APD))
574 {
575 ret = mMessageBox(M_WINDOW(p), NULL, M_TR_T2(TRGROUP_MESSAGE, TRID_MES_SAVE_APD),
576 MMESBOX_YES | MMESBOX_CANCEL | MMESBOX_NOTSHOW, MMESBOX_CANCEL);
577
578 //メッセージ表示しない
579
580 if(ret & MMESBOX_NOTSHOW)
581 APP_CONF->optflags ^= CONFIG_OPTF_MES_SAVE_APD;
582
583 return (ret & MMESBOX_YES)? 1: 0;
584 }
585
586 //上書き保存メッセージ
587
588 if(APP_CONF->optflags & CONFIG_OPTF_MES_SAVE_OVERWRITE)
589 {
590 mStr str = MSTR_INIT;
591
592 mStrPathGetFileName(&str, p->strFilename.buf);
593 mStrAppendText(&str, "\n\n");
594 mStrAppendText(&str, M_TR_T2(TRGROUP_MESSAGE, TRID_MES_SAVE_OVERWRITE));
595
596 ret = mMessageBox(M_WINDOW(p), NULL, str.buf,
597 MMESBOX_SAVE | MMESBOX_CANCEL | MMESBOX_NOTSHOW, MMESBOX_SAVE);
598
599 mStrFree(&str);
600
601 //メッセージ表示しない
602
603 if(ret & MMESBOX_NOTSHOW)
604 APP_CONF->optflags ^= CONFIG_OPTF_MES_SAVE_OVERWRITE;
605
606 //キャンセル
607
608 if(!(ret & MMESBOX_SAVE))
609 return 0;
610 }
611
612 return 1;
613 }
614
615 /** ファイル名とフォーマットを取得
616 *
617 * @return 保存フォーマット。-1 でキャンセル、-2 で上書き保存 */
618
_save_get_path_and_format(MainWindow * p,mStr * strpath,int savetype,int recentno)619 static int _save_get_path_and_format(MainWindow *p,
620 mStr *strpath,int savetype,int recentno)
621 {
622 int ret,type,format;
623 int type_to_format[] = {
624 FILEFORMAT_APD, FILEFORMAT_PSD, FILEFORMAT_PNG,
625 FILEFORMAT_JPEG, FILEFORMAT_BMP
626 };
627
628 //-------- 上書き保存
629 /* 新規状態、または上書きできない場合は別名保存へ */
630
631 if(savetype == MAINWINDOW_SAVEFILE_OVERWRITE && !mStrIsEmpty(&p->strFilename))
632 {
633 ret = _save_message(p);
634
635 if(ret == 0)
636 //キャンセル
637 return -1;
638 else if(ret == 1)
639 {
640 //上書き保存
641
642 mStrCopy(strpath, &p->strFilename);
643 return -2;
644 }
645 }
646
647 //------- 別名保存、複製保存
648
649 //初期ファイル名
650
651 if(!mStrIsEmpty(&p->strFilename))
652 mStrPathGetFileNameNoExt(strpath, p->strFilename.buf);
653
654 //種類の初期選択
655
656 type = FILETYPE_APD;
657
658 if(savetype == MAINWINDOW_SAVEFILE_DUP)
659 {
660 //複製時は指定フォーマット
661
662 if(APP_CONF->savedup_type == 0)
663 {
664 //現在のファイルと同じ
665
666 if(!mStrIsEmpty(&p->strFilename))
667 type = _save_format_to_type(p->fileformat);
668 }
669 else
670 type = APP_CONF->savedup_type - 1;
671 }
672
673 //ダイアログ
674
675 ret = mSysDlgSaveFile(M_WINDOW(p),
676 "AzPainter (*.apd)\t*.apd\t"
677 "PhotoShop (*.psd)\t*.psd\t"
678 "PNG (*.png)\t*.png\t"
679 "JPEG (*.jpg)\t*.jpg\t"
680 "BMP (*.bmp)\t*.bmp\t",
681 type, APP_CONF->strRecentSaveDir[recentno].buf, 0, strpath, &type);
682
683 if(!ret) return -1;
684
685 //フォーマット取得
686
687 format = type_to_format[type];
688
689 //拡張子セット
690
691 _save_set_ext(strpath, format);
692
693 return format;
694 }
695
696
697 //============================
698 // ファイル保存 main
699 //============================
700
701
702 typedef struct
703 {
704 const char *filename;
705 uint32_t format;
706 }_thdata_save;
707
708
709 /** 保存スレッド処理 */
710
_thread_save(mPopupProgress * prog,void * data)711 static int _thread_save(mPopupProgress *prog,void *data)
712 {
713 _thdata_save *p = (_thdata_save *)data;
714 int ret;
715 uint32_t format;
716
717 format = p->format;
718
719 //PNG + ALPHA
720
721 if((format & FILEFORMAT_PNG)
722 && (APP_CONF->save.flags & CONFIG_SAVEOPTION_F_PNG_ALPHA_CHANNEL))
723 format |= FILEFORMAT_ALPHA_CHANNEL;
724
725 //
726
727 if(format & FILEFORMAT_APD)
728 {
729 //----- APD v3
730
731 ret = drawFile_save_apd_v3(APP_DRAW, p->filename, prog);
732 }
733 else if(format & FILEFORMAT_PSD)
734 {
735 //----- PSD
736
737 if(!drawImage_blendImage_RGB8(APP_DRAW))
738 return FALSE;
739
740 if(APP_CONF->save.psd_type == 0)
741 //レイヤ維持
742 ret = drawFile_save_psd_layer(APP_DRAW, p->filename, prog);
743 else
744 {
745 //1枚絵
746 ret = drawFile_save_psd_image(APP_DRAW, APP_CONF->save.psd_type,
747 p->filename, prog);
748 }
749
750 drawUpdate_blendImage_full(APP_DRAW);
751 }
752 else
753 {
754 //----- PNG/JPEG/BMP
755
756 if(format & FILEFORMAT_ALPHA_CHANNEL)
757 //RGBA8
758 drawImage_blendImage_RGBA8(APP_DRAW);
759 else
760 {
761 //RGB8
762
763 if(!drawImage_blendImage_RGB8(APP_DRAW))
764 return FALSE;
765 }
766
767 ret = drawFile_save_image(APP_DRAW, p->filename, format, prog);
768
769 drawUpdate_blendImage_full(APP_DRAW);
770 }
771
772 return ret;
773 }
774
775 /** ファイル保存
776 *
777 * @param savetype [0]上書き保存 [1]別名保存 [2]複製保存
778 * @param recentno ディレクトリ履歴番号
779 * @param FALSE でキャンセルされた */
780
MainWindow_saveFile(MainWindow * p,int savetype,int recentno)781 mBool MainWindow_saveFile(MainWindow *p,int savetype,int recentno)
782 {
783 mStr str = MSTR_INIT,strdir = MSTR_INIT;
784 uint32_t format;
785 int ret;
786 _thdata_save dat;
787
788 //パスとフォーマット取得
789
790 ret = _save_get_path_and_format(p, &str, savetype, recentno);
791 if(ret == -1)
792 {
793 mStrFree(&str);
794 return FALSE;
795 }
796
797 format = (ret == -2)? p->fileformat: ret;
798
799 //保存設定 (PNG/JPEG/PSD)
800 /* 上書き保存で、開いた後一度保存されている場合を除いて保存設定を行う。 */
801
802 if(!(ret == -2 && p->saved)
803 && (format & (FILEFORMAT_PNG | FILEFORMAT_JPEG | FILEFORMAT_PSD)))
804 {
805 if(!SaveOptionDlg_run(M_WINDOW(p), format))
806 {
807 mStrFree(&str);
808 return FALSE;
809 }
810 }
811
812 //スレッド
813
814 dat.filename = str.buf;
815 dat.format = format;
816
817 ret = PopupThread_run(&dat, _thread_save);
818
819 //失敗
820
821 if(ret != 1)
822 {
823 MainWindow_apperr(APPERR_FAILED, NULL);
824
825 mStrFree(&str);
826 return TRUE;
827 }
828
829 //----- 成功
830
831 //編集ファイル情報
832
833 if(savetype != MAINWINDOW_SAVEFILE_DUP)
834 {
835 mStrCopy(&p->strFilename, &str);
836
837 p->fileformat = format;
838 p->saved = TRUE;
839
840 //タイトル
841
842 MainWindow_setTitle(p);
843
844 //undo データ変更フラグ OFF
845
846 Undo_clearUpdateFlag();
847 }
848
849 //ファイル履歴
850
851 _add_recent_file(p, str.buf);
852
853 //ディレクトリ履歴
854
855 mStrPathGetDir(&strdir, str.buf);
856
857 mStrArrayAddRecent(APP_CONF->strRecentSaveDir, CONFIG_RECENTDIR_NUM, strdir.buf, TRUE);
858
859 //
860
861 mStrFree(&str);
862 mStrFree(&strdir);
863
864 return TRUE;
865 }
866