Rev 539 | Rev 544 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 539 | Rev 541 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
2 | This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
2 | This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
3 | Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net |
3 | Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net |
4 | Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft |
4 | Copyright (C) 2018-2023 Daniel Marschall, ViaThinkSoft |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify |
6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 2 of the License, or |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. |
9 | (at your option) any later version. |
Line 217... | Line 217... | ||
217 | free(val); |
217 | free(val); |
218 | if (format_version > 0) { |
218 | if (format_version > 0) { |
219 | simplewarning_id(MSG_FILTERS_UNLIMITED_WARNING_ID); |
219 | simplewarning_id(MSG_FILTERS_UNLIMITED_WARNING_ID); |
220 | 220 | ||
221 | val = _ffx_read_str(&q); |
221 | val = _ffx_read_str(&q); |
- | 222 | if (strlen(val) >= sizeof(gdata->parm.szTitle)) { |
|
- | 223 | val[sizeof(gdata->parm.szTitle) - 1] = '\0'; |
|
- | 224 | } |
|
222 | strcpy(gdata->parm.szTitle, val); |
225 | strcpy(gdata->parm.szTitle, val); |
223 | free(val); |
226 | free(val); |
224 | 227 | ||
225 | val = _ffx_read_str(&q); |
228 | val = _ffx_read_str(&q); |
- | 229 | if (strlen(val) >= sizeof(gdata->parm.szCategory)) { |
|
- | 230 | val[sizeof(gdata->parm.szCategory) - 1] = '\0'; |
|
- | 231 | } |
|
226 | strcpy(gdata->parm.szCategory, val); |
232 | strcpy(gdata->parm.szCategory, val); |
227 | free(val); |
233 | free(val); |
228 | 234 | ||
229 | val = _ffx_read_str(&q); |
235 | val = _ffx_read_str(&q); |
- | 236 | if (strlen(val) >= sizeof(gdata->parm.szAuthor)) { |
|
- | 237 | val[sizeof(gdata->parm.szAuthor) - 1] = '\0'; |
|
- | 238 | } |
|
230 | strcpy(gdata->parm.szAuthor, val); |
239 | strcpy(gdata->parm.szAuthor, val); |
231 | free(val); |
240 | free(val); |
232 | 241 | ||
233 | val = _ffx_read_str(&q); |
242 | val = _ffx_read_str(&q); |
- | 243 | if (strlen(val) >= sizeof(gdata->parm.szCopyright)) { |
|
- | 244 | val[sizeof(gdata->parm.szCopyright) - 1] = '\0'; |
|
- | 245 | } |
|
234 | strcpy(gdata->parm.szCopyright, val); |
246 | strcpy(gdata->parm.szCopyright, val); |
235 | free(val); |
247 | free(val); |
236 | 248 | ||
237 | // Channels I, R, G, B, A |
249 | // Channels I, R, G, B, A |
238 | for (i = 0; i < 4; i++) { |
250 | for (i = 0; i < 4; i++) { |
Line 241... | Line 253... | ||
241 | char* val2 = _ffx_read_str(&q); |
253 | char* val2 = _ffx_read_str(&q); |
242 | if (strcmp(val, "0") != 0) { |
254 | if (strcmp(val, "0") != 0) { |
243 | // "Intro channel" existing |
255 | // "Intro channel" existing |
244 | // C++ wrong warning: Using uninitialized memory "val2" (C6001) |
256 | // C++ wrong warning: Using uninitialized memory "val2" (C6001) |
245 | #pragma warning(suppress : 6001) |
257 | #pragma warning(suppress : 6001) |
246 | char* combined = (char*)malloc(strlen(val) + strlen(",") + strlen(val2) + 1); |
258 | char* combined = (char*)malloc(strlen(val) + strlen(",") + strlen(val2) + 1/*NUL byte*/); |
247 | if (combined != NULL) { |
259 | if (combined != NULL) { |
248 | sprintf(combined, "%s,%s", val, val2); |
260 | sprintf(combined, "%s,%s", val, val2); |
249 | free(val); |
261 | free(val); |
250 | free(val2); |
262 | free(val2); |
251 | val = combined; |
263 | val = combined; |
Line 288... | Line 300... | ||
288 | if (format_version >= 12) { |
300 | if (format_version >= 12) { |
289 | // Format FFX1.2 has prefixes {S} = Slider, {C} = Checkbox, none = Slider |
301 | // Format FFX1.2 has prefixes {S} = Slider, {C} = Checkbox, none = Slider |
290 | if ((sliderName[0] == '{') && (sliderName[1] == 'S') && (sliderName[2] == '}')) sliderName += 3; |
302 | if ((sliderName[0] == '{') && (sliderName[1] == 'S') && (sliderName[2] == '}')) sliderName += 3; |
291 | else if ((sliderName[0] == '{') && (sliderName[1] == 'C') && (sliderName[2] == '}')) sliderName += 3; |
303 | else if ((sliderName[0] == '{') && (sliderName[1] == 'C') && (sliderName[2] == '}')) sliderName += 3; |
292 | } |
304 | } |
- | 305 | if (strlen(val) >= sizeof(gdata->parm.szCtl[i])) { |
|
- | 306 | val[sizeof(gdata->parm.szCtl[i]) - 1] = '\0'; |
|
- | 307 | } |
|
293 | strcpy(gdata->parm.szCtl[i], sliderName); |
308 | strcpy(gdata->parm.szCtl[i], sliderName); |
294 | free(val); |
309 | free(val); |
295 | gdata->parm.ctl_used[i] = (bool32_t)*((byte*)q); |
310 | gdata->parm.ctl_used[i] = (bool32_t)*((byte*)q); |
296 | q += sizeof(byte); |
311 | q += sizeof(byte); |
297 | gdata->parm.val[i] = *((uint32_t*)q); |
312 | gdata->parm.val[i] = *((uint32_t*)q); |
Line 560... | Line 575... | ||
560 | // Check parameters |
575 | // Check parameters |
561 | if (maxOutput == 0) return false; |
576 | if (maxOutput == 0) return false; |
562 | if (inputFile == NULL) return false; |
577 | if (inputFile == NULL) return false; |
563 | // Let input memory be read-only, +1 for terminal zero |
578 | // Let input memory be read-only, +1 for terminal zero |
564 | //char* inputwork = inputFile; |
579 | //char* inputwork = inputFile; |
565 | inputwork = (char*)malloc((size_t)maxInput + 1); |
580 | inputwork = (char*)malloc((size_t)maxInput + 1/*NUL byte*/); |
566 | inputworkinitial = inputwork; |
581 | inputworkinitial = inputwork; |
567 | if (inputwork == NULL) return false; |
582 | if (inputwork == NULL) return false; |
568 | memcpy(inputwork, inputFile, maxInput); |
583 | memcpy(inputwork, inputFile, maxInput); |
569 | inputwork[maxInput] = '\0'; // otherwise strstr() will crash |
584 | inputwork[maxInput] = '\0'; // otherwise strstr() will crash |
570 | 585 | ||
Line 582... | Line 597... | ||
582 | if (x) memcpy(x, "Copyright:", strlen("Copyright:")); |
597 | if (x) memcpy(x, "Copyright:", strlen("Copyright:")); |
583 | x = strstr(inputwork, "AUTHOR:"); |
598 | x = strstr(inputwork, "AUTHOR:"); |
584 | if (x) memcpy(x, "Author:", strlen("Author:")); |
599 | if (x) memcpy(x, "Author:", strlen("Author:")); |
585 | // Controls: |
600 | // Controls: |
586 | for (i = 0; i < 8; i++) { |
601 | for (i = 0; i < 8; i++) { |
587 | k1 = (char*)malloc(strlen("Control X:") + 1); |
602 | k1 = (char*)malloc(strlen("Control X:") + 1/*NUL byte*/); |
588 | sprintf(k1, "Control %d:", (int)i); |
603 | sprintf(k1, "Control %d:", (int)i); |
589 | x = strstr(inputwork, k1); |
604 | x = strstr(inputwork, k1); |
590 | if (x) { |
605 | if (x) { |
591 | k2 = (char*)malloc(strlen("ctl[X]: ") + 1); |
606 | k2 = (char*)malloc(strlen("ctl[X]: ") + 1/*NUL byte*/); |
592 | sprintf(k2, "ctl[%d]: ", (int)i); |
607 | sprintf(k2, "ctl[%d]: ", (int)i); |
593 | memcpy(x, k2, strlen(k2)); |
608 | memcpy(x, k2, strlen(k2)); |
594 | x += strlen("ctl[X]"); |
609 | x += strlen("ctl[X]"); |
595 | _ffdcomp_removebrackets(x, inputwork + maxInput - 1); |
610 | _ffdcomp_removebrackets(x, inputwork + maxInput - 1); |
596 | free(k2); |
611 | free(k2); |
597 | } |
612 | } |
598 | free(k1); |
613 | free(k1); |
599 | } |
614 | } |
600 | // Maps: |
615 | // Maps: |
601 | for (i = 0; i < 4; i++) { |
616 | for (i = 0; i < 4; i++) { |
602 | k1 = (char*)malloc(strlen("Map X:") + 1); |
617 | k1 = (char*)malloc(strlen("Map X:") + 1/*NUL byte*/); |
603 | sprintf(k1, "Map %d:", (int)i); |
618 | sprintf(k1, "Map %d:", (int)i); |
604 | x = strstr(inputwork, k1); |
619 | x = strstr(inputwork, k1); |
605 | if (x) { |
620 | if (x) { |
606 | k2 = (char*)malloc(strlen("map[X]:") + 1); |
621 | k2 = (char*)malloc(strlen("map[X]:") + 1/*NUL byte*/); |
607 | sprintf(k2, "map[%d]:", (int)i); |
622 | sprintf(k2, "map[%d]:", (int)i); |
608 | memcpy(x, k2, strlen(k2)); |
623 | memcpy(x, k2, strlen(k2)); |
609 | x += strlen("map[X]"); |
624 | x += strlen("map[X]"); |
610 | _ffdcomp_removebrackets(x, inputwork + maxInput - 1); |
625 | _ffdcomp_removebrackets(x, inputwork + maxInput - 1); |
611 | free(k2); |
626 | free(k2); |
Line 714... | Line 729... | ||
714 | if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) { |
729 | if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) { |
715 | if ((h = readfileintohandle(refnum))) { |
730 | if ((h = readfileintohandle(refnum))) { |
716 | FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h); |
731 | FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h); |
717 | char* q = PILOCKHANDLE(h, false); |
732 | char* q = PILOCKHANDLE(h, false); |
718 | 733 | ||
719 | char out[256]; |
734 | char dummy[256]; |
720 | if (_picoReadProperty(q, count, "Title", out, sizeof(out), false)) { |
735 | if (_picoReadProperty(q, count, "Title", dummy, sizeof(dummy), false)) { |
721 | int i; |
736 | int i; |
722 | 737 | ||
723 | // Plugin infos |
738 | // Plugin infos |
724 | _picoReadProperty(q, count, "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle), false); |
739 | _picoReadProperty(q, count, "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle), false); |
725 | _picoReadProperty(q, count, "Category", gdata->parm.szCategory, sizeof(gdata->parm.szCategory), false); |
740 | _picoReadProperty(q, count, "Category", gdata->parm.szCategory, sizeof(gdata->parm.szCategory), false); |
Line 741... | Line 756... | ||
741 | expr[i] = my_strdup(gdata->parm.szFormula[i]); |
756 | expr[i] = my_strdup(gdata->parm.szFormula[i]); |
742 | } |
757 | } |
743 | 758 | ||
744 | for (i = 0; i < 8; i++) { |
759 | for (i = 0; i < 8; i++) { |
745 | int v; |
760 | int v; |
746 | char keyname[7+1], tmp[5]; |
761 | char keyname[6/*strlen("ctl[X]")*/ + 1/*strlen("\0")*/], tmp[5]; |
747 | 762 | ||
748 | // Slider names |
763 | // Slider names |
749 | sprintf(keyname, "ctl[%d]", i); |
764 | sprintf(keyname, "ctl[%d]", i); |
750 | _picoReadProperty(q, count, keyname, gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i]), false); |
765 | _picoReadProperty(q, count, keyname, gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i]), false); |
751 | 766 | ||
Line 763... | Line 778... | ||
763 | gdata->parm.val[i] = slider[i] = (uint8_t)v; |
778 | gdata->parm.val[i] = slider[i] = (uint8_t)v; |
764 | } |
779 | } |
765 | 780 | ||
766 | // Map names |
781 | // Map names |
767 | for (i = 0; i < 4; i++) { |
782 | for (i = 0; i < 4; i++) { |
768 | char keyname[7+1]; |
783 | char keyname[6/*strlen("map[X]")*/ + 1/*strlen("\0")*/]; |
769 | sprintf(keyname, "map[%d]", i); |
784 | sprintf(keyname, "map[%d]", i); |
770 | _picoReadProperty(q, count, keyname, gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i]), false); |
785 | _picoReadProperty(q, count, keyname, gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i]), false); |
771 | } |
786 | } |
772 | 787 | ||
773 | //These will be set when the expressions are evaluated anyway. So this part is optional: |
788 | //These will be set when the expressions are evaluated anyway. So this part is optional: |
Line 795... | Line 810... | ||
795 | if (argMaxOutLength == 0) return false; |
810 | if (argMaxOutLength == 0) return false; |
796 | if (fileContents == NULL) return false; |
811 | if (fileContents == NULL) return false; |
797 | 812 | ||
798 | // Handle argMaxInputLength |
813 | // Handle argMaxInputLength |
799 | //char* inputwork = fileContents; |
814 | //char* inputwork = fileContents; |
800 | inputwork = (char*)malloc((size_t)argMaxInputLength + 1); |
815 | inputwork = (char*)malloc((size_t)argMaxInputLength + 1/*NUL byte*/); |
801 | if (inputwork == NULL) return false; |
816 | if (inputwork == NULL) return false; |
802 | memcpy(inputwork, fileContents, argMaxInputLength); |
817 | memcpy(inputwork, fileContents, argMaxInputLength); |
803 | inputwork[argMaxInputLength] = '\0'; |
818 | inputwork[argMaxInputLength] = '\0'; |
804 | 819 | ||
805 | // Prepare the input file contents to make it easier parse-able |
820 | // Prepare the input file contents to make it easier parse-able |
806 | iTmp = strlen(inputwork) + strlen("\n\n["); |
821 | iTmp = strlen(inputwork) + strlen("\n\n["); |
807 | tmpFileContents = (char*)malloc(iTmp + 1); |
822 | tmpFileContents = (char*)malloc(iTmp + 1/*NUL byte*/); |
808 | if (tmpFileContents == NULL) return false; |
823 | if (tmpFileContents == NULL) return false; |
809 | sprintf(tmpFileContents, "\n%s\n[", inputwork); |
824 | sprintf(tmpFileContents, "\n%s\n[", inputwork); |
810 | for (iTmp = 0; iTmp < strlen(tmpFileContents); iTmp++) { |
825 | for (iTmp = 0; iTmp < strlen(tmpFileContents); iTmp++) { |
811 | if (tmpFileContents[iTmp] == '\r') tmpFileContents[iTmp] = '\n'; |
826 | if (tmpFileContents[iTmp] == '\r') tmpFileContents[iTmp] = '\n'; |
812 | } |
827 | } |
813 | 828 | ||
814 | // Find the section begin |
829 | // Find the section begin |
815 | iTmp = strlen(section) + strlen("\n[]\n"); |
830 | iTmp = strlen(section) + strlen("\n[]\n"); |
816 | tmpSection = (char*)malloc(iTmp + 1); |
831 | tmpSection = (char*)malloc(iTmp + 1/*NUL byte*/); |
817 | if (tmpSection == NULL) return false; |
832 | if (tmpSection == NULL) return false; |
818 | sprintf(tmpSection, "\n[%s]\n", section); |
833 | sprintf(tmpSection, "\n[%s]\n", section); |
819 | tmpStart = strstr(tmpFileContents, tmpSection); |
834 | tmpStart = strstr(tmpFileContents, tmpSection); |
820 | if (tmpStart == NULL) return false; |
835 | if (tmpStart == NULL) return false; |
821 | tmpStart += iTmp; |
836 | tmpStart += iTmp; |
Line 870... | Line 885... | ||
870 | 885 | ||
871 | Handle h; |
886 | Handle h; |
872 | Boolean res = false; |
887 | Boolean res = false; |
873 | FILEREF refnum; |
888 | FILEREF refnum; |
874 | 889 | ||
- | 890 | // TODO: Decode UTF-8 to ANSI (or "?" for unknown characters) |
|
- | 891 | ||
875 | if (!fileHasExtension(sfr, TEXT(".guf"))) return false; |
892 | if (!fileHasExtension(sfr, TEXT(".guf"))) return false; |
876 | 893 | ||
877 | if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) { |
894 | if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) { |
878 | if ((h = readfileintohandle(refnum))) { |
895 | if ((h = readfileintohandle(refnum))) { |
879 | FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h); |
896 | FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h); |
Line 896... | Line 913... | ||
896 | FSClose(refnum); |
913 | FSClose(refnum); |
897 | return false; |
914 | return false; |
898 | } |
915 | } |
899 | if (_gufReadProperty(q, count, "Info", "Title", out, sizeof(out))) { |
916 | if (_gufReadProperty(q, count, "Info", "Title", out, sizeof(out))) { |
900 | int i; |
917 | int i; |
- | 918 | char tmp[256]; |
|
- | 919 | char* tmp2; |
|
901 | 920 | ||
902 | // Plugin infos |
921 | // Plugin infos |
903 | _gufReadProperty(q, count, "Info", "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle)); |
922 | _gufReadProperty(q, count, "Info", "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle)); |
904 | _gufReadProperty(q, count, "Info", "Category", gdata->parm.szCategory, sizeof(gdata->parm.szCategory)); // TODO: only last part of "/" |
923 | _gufReadProperty(q, count, "Info", "Category", tmp, sizeof(tmp)); |
- | 924 | tmp2 = strrchr(tmp, '/'); |
|
- | 925 | if (tmp2 == NULL) { |
|
- | 926 | strcpy(gdata->parm.szCategory, tmp); |
|
- | 927 | } else { |
|
- | 928 | strcpy(gdata->parm.szCategory, tmp2+1); |
|
- | 929 | } |
|
905 | _gufReadProperty(q, count, "Info", "Author", gdata->parm.szAuthor, sizeof(gdata->parm.szAuthor)); |
930 | _gufReadProperty(q, count, "Info", "Author", gdata->parm.szAuthor, sizeof(gdata->parm.szAuthor)); |
906 | _gufReadProperty(q, count, "Info", "Copyright", gdata->parm.szCopyright, sizeof(gdata->parm.szCopyright)); |
931 | _gufReadProperty(q, count, "Info", "Copyright", gdata->parm.szCopyright, sizeof(gdata->parm.szCopyright)); |
907 | //_gufReadProperty(q, count, "Filter Factory", "8bf", gdata->parm.xxx, sizeof(gdata->parm.xxx)); |
932 | //_gufReadProperty(q, count, "Filter Factory", "8bf", gdata->parm.xxx, sizeof(gdata->parm.xxx)); |
908 | 933 | ||
909 | // Expressions |
934 | // Expressions |
Line 920... | Line 945... | ||
920 | expr[i] = my_strdup(gdata->parm.szFormula[i]); |
945 | expr[i] = my_strdup(gdata->parm.szFormula[i]); |
921 | } |
946 | } |
922 | 947 | ||
923 | for (i = 0; i < 8; i++) { |
948 | for (i = 0; i < 8; i++) { |
924 | int v; |
949 | int v; |
925 | char keyname[10 + 1], tmp[5]; |
950 | char keyname[9/*strlen("Control X")*/ + 1/*strlen("\0")*/], tmp[5]; |
926 | sprintf(keyname, "Control %d", i); |
951 | sprintf(keyname, "Control %d", i); |
927 | 952 | ||
928 | // Slider names |
953 | // Slider names |
929 | _gufReadProperty(q, count, keyname, "Label", gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i])); |
954 | _gufReadProperty(q, count, keyname, "Label", gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i])); |
930 | 955 | ||
Line 938... | Line 963... | ||
938 | gdata->parm.val[i] = slider[i] = (uint8_t)v; |
963 | gdata->parm.val[i] = slider[i] = (uint8_t)v; |
939 | } |
964 | } |
940 | 965 | ||
941 | // Map names |
966 | // Map names |
942 | for (i = 0; i < 4; i++) { |
967 | for (i = 0; i < 4; i++) { |
943 | char keyname[6 + 1]; |
968 | char keyname[5/*strlen("Map X")*/ + 1/*strlen("\0")*/]; |
944 | sprintf(keyname, "Map %d", i); |
969 | sprintf(keyname, "Map %d", i); |
945 | _gufReadProperty(q, count, keyname, "Label", gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i])); |
970 | _gufReadProperty(q, count, keyname, "Label", gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i])); |
946 | } |
971 | } |
947 | 972 | ||
948 | //These will be set when the expressions are evaluated anyway. So this part is optional: |
973 | //These will be set when the expressions are evaluated anyway. So this part is optional: |