diff --git a/.gitattributes b/.gitattributes index dfe0770..4bb50dc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ # Auto detect text files and perform LF normalization -* text=auto +* text eol=lf \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..6895c03 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,23 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "E:/Amiga/KrustWB3/Output/Dev/SDK/NDK_3.9/Include/include_h", + "E:/Amiga/KrustWB3/Output/Dev/vbcc_posix/targets/m68k-amigaos/include" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.16299.0", + "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.11.25503/bin/Hostx64/x64/cl.exe", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a9e011b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "files.associations": { + "*.s": "m68k", + "startup.h": "c", + "types.h": "c", + "dos.h": "c", + "workbench.h": "c", + "tasks.h": "c", + "lists.h": "c", + "icon.h": "c", + "icon_pragmas.h": "c", + "icon_protos.h": "c", + "icon_lib.h": "c", + "exec_protos.h": "c", + "dos_pragmas.h": "c", + "dos_protos.h": "c", + "exec.h": "c", + "exec_pragmas.h": "c", + "dirent.h": "c", + "unistd.h": "c" + }, + "C_Cpp.intelliSenseEngineFallback": "Disabled" +} \ No newline at end of file diff --git a/IconAlign b/IconAlign new file mode 100644 index 0000000..57c789d Binary files /dev/null and b/IconAlign differ diff --git a/b b/b new file mode 100644 index 0000000..aad140b --- /dev/null +++ b/b @@ -0,0 +1,3 @@ +; -v for verbose +vc src/main.c -stack-check -lamiga -lposix -IDev:vbcc_posix/targets/m68k-amigaos/include -LDev:vbcc_posix/targets/m68k-amigaos/lib -DBUILD_PLATFORM_AMIGA -c99 -o IconAlign +copy IconAlign r \ No newline at end of file diff --git a/b.bat b/b.bat new file mode 100644 index 0000000..098cba0 --- /dev/null +++ b/b.bat @@ -0,0 +1,4 @@ +@echo off +REM -v for verbose +vc src/main.c -stack-check -size -lamiga -lposix -IE:\Amiga\KrustWB3\Output\Dev\vbcc_posix\targets\m68k-amigaos\include -LE:\Amiga\KrustWB3\Output\Dev\vbcc_posix\targets\m68k-amigaos\lib -DBUILD_PLATFORM_WIN -o IconAlign +copy IconAlign r \ No newline at end of file diff --git a/r b/r new file mode 100644 index 0000000..57c789d Binary files /dev/null and b/r differ diff --git a/src/main.asm b/src/main.asm new file mode 100644 index 0000000..8e22a5b --- /dev/null +++ b/src/main.asm @@ -0,0 +1 @@ + idnt "src/main.c" diff --git a/src/main.c b/src/main.c index 3442d9a..ca0c274 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,350 @@ -#include +#include +#include +#include +#include -int main() +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// VBCC +extern size_t __stack_usage; + +// Version tag +#define VERSTAG "\0$VER: IconAlign 0.1 (18.11.2018)" +UBYTE versiontag[] = VERSTAG; + +// Build Platform +#ifdef BUILD_PLATFORM_AMIGA +const char *BuildPlatform = "Amiga"; +#elif BUILD_PLATFORM_WIN +const char *BuildPlatform = "Win"; +#else +const char *BuildPlatform = "Unknown"; +#endif + +// Libraries +// int _IconBaseVer = 45; +struct Library *DosBase = NULL; +struct Library *IconBase = NULL; + +// Logging +short verbose = FALSE; +void Information(const char *fmt, ...); +void Verbose(const char *fmt, ...); + +// String/Path handling +size_t maxPathTreshold = PATH_MAX - 2; +short StringEndsWith(const char *str, const char *suffix); +void StringToLower(char *str, unsigned int strLen, unsigned int offset); + +// Icon alignment +long XAlignment = 16; +long YAlignment = 16; +unsigned int AlignCurrentWorkingDir(); +unsigned int AlignDir(unsigned char *diskObjectName); +unsigned int AlignIcon(unsigned char *diskObjectName); + +int main(int argc, char **argv) +{ + // Open libraries + DosBase = OpenLibrary("dos.library", 40L); + if (!DosBase) + { + Information("Failed to open dos.library 40\n"); + return RETURN_ERROR; + } + + IconBase = OpenLibrary("icon.library", 45L); + if (!IconBase) + { + Information("Failed to open icon.library 45\n"); + return RETURN_ERROR; + } + + // check arguments + long argArray[] = + { + 0, + // 0, + 0}; + struct RDArgs *rdargs = ReadArgs("FILE/K,DIR/K,VERBOSE/S", argArray, NULL); + if (!rdargs) + { + // GetFa + PrintFault(IoErr(), NULL); + return RETURN_ERROR; + } + + verbose = argArray[2] == DOSTRUE; + if (verbose) + { + Verbose(" VERBOSE logging active\n"); + } + STRPTR fileOption = (STRPTR)argArray[0]; + if (fileOption) + { + Verbose(" FILE=[%s]\n", fileOption); + } + unsigned char *dirOption = (unsigned char *)argArray[1]; + if (dirOption) + { + Verbose(" DIR=[%s]\n", dirOption); + } + // if (!fileOption && !folderOption) + // { + // Information("please provide FILE or FOLDER option\n"); + // return RETURN_ERROR; + // } + + unsigned int fixCount = 0; + if (!fileOption && !dirOption) + { + fixCount = AlignCurrentWorkingDir(); + } + else if (fileOption) + { + fixCount = AlignIcon(fileOption); + } + else if (dirOption) + { + size_t dirOptionLen = strlen(dirOption); + if (dirOptionLen == 0) + { + fixCount = AlignCurrentWorkingDir(); + } + else + { + fixCount = AlignDir(dirOption); + } + } + if (fixCount == 0) + { + Information("No icons found\n"); + } + + // if (argc != 2) + // { + // printf("incorrect args!\n"); + // printf("usage: IconAlign FILE\n"); + // return RETURN_ERROR; + // } + + if (rdargs) + { + FreeArgs(rdargs); + } + CloseLibrary(IconBase); + + Verbose("Build platform: %s\n", BuildPlatform); + Verbose("Stack used: %lu\n", (unsigned long)__stack_usage); + // Verbose("IconBase: %p\n", (void *)IconBase); + // Verbose("SysBase: %p\n", (void *)SysBase); + Verbose("DosBase: %p\n", (void *)DosBase); + + return RETURN_OK; +} + +// Logging +void Verbose(const char *fmt, ...) +{ + if (!verbose) + return; + + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); +} + +void Information(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); +} + +// String/Path handling +short StringEndsWith(const char *str, const char *suffix) +{ + if (!str || !suffix) + { + return FALSE; + } + size_t lenstr = strlen(str); + size_t lensuffix = strlen(suffix); + if (lensuffix > lenstr) + { + return FALSE; + } + return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; +} + +void StringToLower(char *str, unsigned int strLen, unsigned int offset) +{ + // Verbose("StringToLower from: %s\n", str); + if (offset >= strLen) + { + return; + } + for (int i = offset; i < strLen; i++) + { + unsigned char curr = str[i]; + if (curr >= 'A' && curr <= 'Z') + { + str[i] = curr + 32; + } + // TODO: Not really needed for this app! But åäö etc. + } + // Verbose("StringToLower result: %s\n", str); +} + +// Icon management +unsigned int AlignCurrentWorkingDir() +{ + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) != NULL) + { + Verbose("Using current working dir: %s\n", cwd); + } + unsigned int fixCount = AlignDir(cwd); + return fixCount; +} + +unsigned int AlignDir(unsigned char *dirName) +{ + size_t dirNameLen = strlen(dirName); + if (dirNameLen > maxPathTreshold) + { + Information("path \"%s\" is too long - skipping!\n", dirName); + return 0; + } + if (!StringEndsWith(dirName, "/") && !StringEndsWith(dirName, ":")) + { + Verbose("Appending \"/\" to dir\n"); + unsigned char fixedDirName[PATH_MAX]; + strcpy(fixedDirName, dirName); + fixedDirName[dirNameLen] = '/'; + fixedDirName[dirNameLen + 1] = 0; + dirName = fixedDirName; + dirNameLen += 1; + } + + unsigned int fixCount = 0; + DIR *dir = opendir(dirName); + struct dirent *direntry; + if (dir) + { + // Verbose("dirNameLen: %i", dirNameLen); + while ((direntry = readdir(dir)) != NULL) + { + size_t dirEntryLen = strlen(direntry->d_name); + size_t fullLen = dirNameLen + dirEntryLen; + if (fullLen > PATH_MAX - 2) + { + Information("full path to %s is too long - skipping!\n", direntry->d_name); + } + else + { + unsigned char fullPath[PATH_MAX]; + strcpy(fullPath, dirName); + strcat(fullPath, direntry->d_name); + StringToLower(fullPath, fullLen, fullLen - 4); + if (StringEndsWith(fullPath, ".info")) + { + fullPath[fullLen - 5] = 0; + // Verbose("fullPath: %s\n", fullPath); + fixCount += AlignIcon(fullPath); + } + } + //printf("%s\n", direntry->d_name); + } + closedir(dir); + } + return fixCount; +} + +unsigned int AlignIcon(unsigned char *diskObjectName) +{ + struct DiskObject *diskObject = GetDiskObject(diskObjectName); + if (diskObject) + { + Verbose("Icon found: %s\n", diskObjectName); + // Verbose("do_Magic: %x\n", diskObject->do_Magic); + Verbose(" Version: %hi\n", diskObject->do_Version); + Verbose(" do_Type: %i\n", (int)diskObject->do_Type); + Verbose(" do_DefaultTool: %s\n", diskObject->do_DefaultTool); + // Verbose("do_DefaultTool: "); + // Verbose(diskObject->do_DefaultTool); + // Verbose("\n"); + Verbose(" do_CurrentX: %li\n", diskObject->do_CurrentX); + Verbose(" do_CurrentY: %li\n", diskObject->do_CurrentY); + // Verbose(" Width: %hi\n", diskObject->); + Verbose(" Width: %hi\n", diskObject->do_Gadget.Width); + Verbose(" Height: %hi\n", diskObject->do_Gadget.Height); + // Verbose(" GadgetRender: %p\n", diskObject->do_Gadget.GadgetRender); + Verbose(" Flags: %hi\n", diskObject->do_Gadget.Flags); + Verbose(" GadgetType: %hi\n", diskObject->do_Gadget.GadgetType); + Verbose(" LeftEdge: %hi\n", diskObject->do_Gadget.LeftEdge); + Verbose(" TopEdge: %hi\n", diskObject->do_Gadget.TopEdge); + + // diskObject->do_CurrentX += 10; + if (diskObject->do_CurrentX == NO_ICON_POSITION && diskObject->do_CurrentX == NO_ICON_POSITION) + { + Information("Skip \"%s\" - no icon position\n", diskObjectName); + return 0; + } + + short xaligned = FALSE; + if (diskObject->do_CurrentX != NO_ICON_POSITION) + { + // Information("Skip X \"%s\" - no icon position for X\n"); + long currx = diskObject->do_CurrentX + (XAlignment / 2); + long newx = currx - (currx % XAlignment); + if (newx != diskObject->do_CurrentX) + { + xaligned = TRUE; + } + // printf("change x from %li to %li\n", currx, newx); + diskObject->do_CurrentX = newx; + // long XAlignment = 16; + // long YAlignment = 16; + } + short yaligned = FALSE; + if (diskObject->do_CurrentY != NO_ICON_POSITION) + { + // Information("Skip Y \"%s\" - no icon position for Y\n"); + // TODO: Align bottom, not top! + long curry = diskObject->do_CurrentY + (YAlignment / 2); + long newy = curry - (curry % YAlignment); + if (newy != diskObject->do_CurrentY) + { + yaligned = TRUE; + diskObject->do_CurrentY = newy; + } + } + + if (!xaligned && !yaligned) + { + Information("Already aligned \"%s\"\n", diskObjectName); + return 0; + } + + PutDiskObject(diskObjectName, diskObject); + FreeDiskObject(diskObject); + + Information("Aligend \"%s\"\n", diskObjectName); + return 1; + } + Verbose("Skipped \"%s\" - icon not found\n", diskObjectName); + return 0; +} diff --git a/tempicons b/tempicons new file mode 100644 index 0000000..b7751ac --- /dev/null +++ b/tempicons @@ -0,0 +1,2 @@ +makedir ram:sys +copy a-system:#?.info ram:sys/ \ No newline at end of file