]> code.delx.au - refind/commitdiff
Added new "icons_dir" configuration file token.
authorsrs5694 <srs5694@users.sourceforge.net>
Wed, 9 May 2012 05:59:17 +0000 (01:59 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Wed, 9 May 2012 05:59:17 +0000 (01:59 -0400)
14 files changed:
BUILDING.txt
Makefile
NEWS.txt
docs/refind/configfile.html
docs/refind/getting.html
docs/refind/themes.html
docs/refind/todo.html
refind.conf-sample
refind/config.c
refind/global.h
refind/icns.c
refind/lib.h
refind/main.c
refind/menu.c

index 2c59bb47e42fd83dffb7f5322a927f46754b961a..91d86f9d579d9a8c7dec3f96254ac25a16352c4b 100644 (file)
@@ -140,3 +140,14 @@ follows:
 You'll then need to activate rEFInd in your EFI. This can be done with
 tools such as "efibootmgr" under Linux or "bless" under OS X. See the
 docs/refind/installing.html file for details.
+
+Note to Distribution Maintainers
+================================
+
+The install.sh script, and therefore the "install" target in the Makefile,
+installs the program directly to the ESP and it modifies the *CURRENT
+COMPUTER's* NVRAM. Thus, you should *NOT* use this target as part of the
+build process for your binary packages (RPMs, Debian packages, etc.).
+(Gentoo could use it in an ebuild, though....) You COULD, however, copy the
+files to a directory somewhere (/usr/share/refind or whatever) and then
+call install.sh as part of the binary package installation process.
index 704334ffdcbcc17111b94ae23501ea5dc4ced7f5..e6f6ca0688c87c909919f693313f731c2cade396 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,17 @@ clean:
        make -C $(LIB_DIR) clean
        make -C $(LOADER_DIR) clean
 
+# NOTE TO DISTRIBUTION MAINTAINERS:
+# The "install" target installs the program directly to the ESP
+# and it modifies the *CURRENT COMPUTER's* NVRAM. Thus, you should
+# *NOT* use this target as part of the build process for your
+# binary packages (RPMs, Debian packages, etc.). (Gentoo could
+# use it in an ebuild, though....) You COULD, however, copy the
+# files to a directory somewhere (/usr/share/refind or whatever)
+# and then call install.sh as part of the binary package
+# installation process.
+
 install:
        ./install.sh
+
 # DO NOT DELETE
index 13c810726324d45f6453611be6baaa6cc923d9bc..23d3378fb5cbc711ceffb67f827f2fd3bb2437ba 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,8 +1,22 @@
 0.3.4 (?/??/2012):
 ------------------
 
+- Added new configuration file option: "icons_dir", which sets the name
+  of the subdirectory in which icons are found. See the documentation or
+  sample configuration file for a full description.
+
+- Modified Makefile to generate rEFInd binary that includes architecture
+  code -- refind_ia32.efi or refind_x64.efi, rather than the generic
+  refind.efi. This is done mainly to help the install.sh script. The
+  program can be named anything you like on the disk. (The generic name
+  refind.efi is used on unknown architectures.)
+
+- Improved install.sh script: Fixed bug on OS X 10.7 and enable it to be
+  used after building from source code (or via new "make install" Makefile
+  target).
+
 - Improved screen redraws to produce less flicker when moving among the
-  second-row tags.
+  second-row tags or to the last tag on the first row.
 
 0.3.3 (5/6/2012):
 -----------------
index 3e145bb93ca0d7aadbb79cd634a81012147fe30e..2a133663984fbce1610e105de32cefb9cb944886 100644 (file)
@@ -148,6 +148,11 @@ timeout 20
    <td><tt>banner</tt>, <tt>label</tt>, <tt>singleuser</tt>, <tt>hwtest</tt>, <tt>arrows</tt>, or <tt>all</tt></td>
    <td>Removes the specified user interface features. <tt>banner</tt> removes the banner graphic, <tt>label</tt> removes the text description of each tag, <tt>singleuser</tt> removes the single-user option from the Mac OS sub-menu, <tt>hwtest</tt> removes the Mac OS hardware test option, <tt>arrows</tt> removes the arrows to the right or left of the OS tags when rEFInd finds too many OSes to display simultaneously, and <tt>all</tt> removes all of these options. You can specify multiple parameters with this option. The default is to set none of these values.</td>
 </tr>
+<tr>
+   <td><tt>icons_dir</tt></td>
+   <td>directory name</td>
+   <td>Specifies a directory in which custom icons may be found. This directory should contain files with the same names as the files in the standard <tt>icons</tt> directory. The directory name is specified relative to the directory in which the rEFInd binary resides.</td>
+</tr>
 <tr>
    <td><tt>banner</tt></td>
    <td>filename</td>
index 2dc86fb41f438ea5f286c5b2534444f28cf4b892..41c31d0858aef714f4bd2e904239f67c217ca5b9 100644 (file)
@@ -93,7 +93,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <h2>Getting rEFInd from Sourceforge</h2>
 
-<p>You can find the rEFInd source code and binary packages at <a href="http://www.sourceforge.net/projects/refind/">its SourceForge page.</a> Note that rEFInd is OS-independent&mdash;it runs before the OS, so you download the same binary package for any OS. You can obtain rEFInd in three different forms:</p>
+<p>You can find the rEFInd source code and binary packages at <a href="http://www.sourceforge.net/projects/refind/">its SourceForge page.</a> Note that rEFInd is OS-independent&mdash;it runs before the OS, so you download the same binary package for any OS. You can obtain rEFInd in four different forms:</p>
 
 <ul>
 
@@ -132,6 +132,14 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
     your regular hard disk. This can be an extremely valuable diagnostic
     tool if you know about about using an EFI shell.</li>
 
+<li><b><a href="https://sourceforge.net/p/refind/code">Source code via
+    git</a></b>&mdash;If you want to peruse the source code in your Web
+    browser or get the very latest version (including pre-release bug fixes
+    and updates), you can use the Sourceforge git repository. This access
+    method is most useful to programmers, or at least to those who are
+    familiar with programming tools. Note that if you need to ask "what's
+    git?", this is probably not the best way for you to obtain rEFInd.</li>
+
 </ul>
 
 <p>If you're using another platform, you can give rEFInd a try; however, you'll need to build it from source code yourself or track down a binary from another source. (Perhaps by the time you read this it will be included in Linux distributions built for unusual CPUs.)</p>
index 66c60dccb3e66012bf1b462472c8e51f4324e8d5..261a61d57297de8fb2ec5c31c8a10f9e0e2a3942 100644 (file)
@@ -15,7 +15,7 @@
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <p>Originally written: 4/19/2012; last Web page update:
-5/6/2012, referencing rEFInd 0.3.3</p>
+5/6/2012, referencing rEFInd 0.3.4</p>
 
 
 <p>I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!</p>
@@ -96,7 +96,9 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 <ul>
 
-<li>You can create new icons and place them in the <tt>icons</tt> subdirectory. This will affect the appearance of the OS tags, the utility tags, and so on. The names of these icons are fairly self-explanatory. Be aware that rEFInd expects its icons to be in Apple's <a href="http://en.wikipedia.org/wiki/Icns">icon image format (ICNS).</a> You can generate such files easily in various Apple programs, or by using the <a href="http://icns.sourceforge.net/">libicns</a> library (and in particular its <tt>png2icns</tt> program) in Linux.</li>
+<li>You can create new icons, place them in a subdirectory rEFInd's main directory, and tell the program to use the new icons by setting the <tt>icons_dir</tt> token in <tt>refind.conf</tt>. This will affect the appearance of the OS tags, the utility tags, and so on. The names of these icons should match those in the <tt>icons</tt> subdirectory, and are fairly self-explanatory. Be aware that rEFInd expects its icons to be in Apple's <a href="http://en.wikipedia.org/wiki/Icns">icon image format (ICNS).</a> You can generate such files easily in various Apple programs, or by using the <a href="http://icns.sourceforge.net/">libicns</a> library (and in particular its <tt>png2icns</tt> program) in Linux.</li>
+
+<li>You can do as above, but place your new icons in the default <tt>icons</tt> subdirectory. This method is discouraged because using the <tt>install.sh</tt> script to upgrade rEFInd will replace your customized icons.</li>
 
 <li>You can customize the appearance of an individual boot loader by placing an ICNS file in its directory with the same name as the boot loader but with a <tt>.icns</tt> extension. For instance, if your boot loader program is <tt>elilo.efi</tt>, you can create a custom icon by naming it <tt>elilo.icns</tt>.</li>
 
@@ -110,7 +112,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
 </ul>
 
-<p>Of course, not all of these elements are likely to be included in themes. A minimal rEFInd theme would include just some changes to the icons in the <tt>icons</tt> subdirectory. A more thorough theme would include a changed background image or selection backgrounds.</p>
+<p>Of course, not all of these elements are likely to be included in themes. A minimal rEFInd theme would provide just a new icons subdirectory, to be set via <tt>icons_dir</tt>. A more thorough theme would include a changed background image or selection backgrounds.</p>
 
 <p><b>Note:</b> If you'd like to design a logo for rEFInd, please do so! I lack the sort of artistic talent required for creating logos, so I just used plain text. I'd like to have something more eye-catching, though. I don't promise to use the first logo I'm given, but if you have some ideas, or would like to discuss some ideas, feel free to <a href="mailto:rodsmith@rodsbooks.com">e-mail me.</a></p>
 
index b482f26eae73218d1da981efc364ba3eec0fb0ba..19c4d335422aa326aed4edccf55ddac0bd4ddedf 100644 (file)
@@ -121,11 +121,14 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
     theming by replacing icon files. If you'd like to design a new theme
     for rEFInd, feel free to submit it. I might or might not replace the
     icons it uses now (most of which come from the Oxygen Icons package),
-    but I may provide a way to make selecting a theme from one of several
-    installed themes easy, and provide links to themes on this Web site (or
-    even host them on the project's Sourceforge page). For more information
-    on designing themes for rEFInd, see the <a href="themes.html">Theming
-    rEFInd</a> page.</li>
+    but I may provide links to themes on this Web site (or even host them
+    on the project's Sourceforge page). For more information on designing
+    themes for rEFInd, see the <a href="themes.html">Theming rEFInd</a>
+    page.</li>
+
+<li>If the <tt>icons_dir</tt> option points to a non-existent directory,
+    the program displays ugly "icon-missing" icons. It would be better to
+    drop back to the default icon set.</li>
 
 <li>The code could be more flexible in its handling of the sizes of various
     graphical elements, and particularly drawn text. Prior to version
index 2c04c6387b1da8d8669f9493ead3f4f18570bd98..1f44731514252be0427d56fb5b93ee03757a538e 100644 (file)
@@ -21,6 +21,13 @@ timeout 20
 #hideui singleuser
 #hideui all
 
+# Set the name of a subdirectory in which icons are stored. Icons must
+# have the same names they have in the standard directory. The directory
+# name is specified relative to the main rEFInd binary's directory.
+# Default is "icons".
+#
+#icons_dir myicons
+
 # Use a custom title banner instead of the rEFInd icon and name. The file
 # path is relative to the directory where refind.efi is located. The color
 # in the top left corner of the image is used as the background color
index 0a15cc6ebd7c485cab0a6c7bec29f0bc037a2bf6..ebc7d083e4f872b09e0594f997284a2a66e3e586 100644 (file)
@@ -350,6 +350,11 @@ VOID ReadConfig(VOID)
                 }
             }
 
+        } else if ((StriCmp(TokenList[0], L"icons_dir") == 0) && (TokenCount == 2)) {
+           if (GlobalConfig.IconsDir != NULL)
+              FreePool(GlobalConfig.IconsDir);
+           GlobalConfig.IconsDir = StrDuplicate(TokenList[1]);
+
         } else if (StriCmp(TokenList[0], L"scanfor") == 0) {
            for (i = 0; i < NUM_SCAN_OPTIONS; i++) {
               if (i < TokenCount)
index 2cd9b37dcc28e413d8de67092debe6524c7a2d67..678054b6ac3b8b33a9d994f768bb2c1ac3cda243 100644 (file)
@@ -66,6 +66,7 @@
 
 #define NUM_SCAN_OPTIONS 10
 
+#define DEFAULT_ICONS_DIR L"icons"
 
 //
 // global definitions
@@ -164,6 +165,7 @@ typedef struct {
    CHAR16      *DefaultSelection;
    CHAR16      *AlsoScan;
    CHAR16      *DriverDirs;
+   CHAR16      *IconsDir;
    UINTN       ShowTools[NUM_TOOLS];
    CHAR8       ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan
 } REFIT_CONFIG;
index 459dece88172a45411193a3ce1616e06058342db..1bc320245df20ccf0ca3fa51195ac82deec7eaf5 100644 (file)
 
 typedef struct {
     EG_IMAGE    *Image;
-    CHAR16      *Path;
+    CHAR16      *FileName;
     UINTN       PixelSize;
 } BUILTIN_ICON;
 
 BUILTIN_ICON BuiltinIconTable[BUILTIN_ICON_COUNT] = {
-    { NULL, L"icons\\func_about.icns", 48 },
-    { NULL, L"icons\\func_reset.icns", 48 },
-    { NULL, L"icons\\func_shutdown.icns", 48 },
-    { NULL, L"icons\\func_exit.icns", 48 },
-    { NULL, L"icons\\tool_shell.icns", 48 },
-    { NULL, L"icons\\tool_part.icns", 48 },
-    { NULL, L"icons\\tool_rescue.icns", 48 },
-    { NULL, L"icons\\vol_internal.icns", 32 },
-    { NULL, L"icons\\vol_external.icns", 32 },
-    { NULL, L"icons\\vol_optical.icns", 32 },
+   { NULL, L"func_about.icns", 48 },
+   { NULL, L"func_reset.icns", 48 },
+   { NULL, L"func_shutdown.icns", 48 },
+   { NULL, L"func_exit.icns", 48 },
+   { NULL, L"tool_shell.icns", 48 },
+   { NULL, L"tool_part.icns", 48 },
+   { NULL, L"tool_rescue.icns", 48 },
+   { NULL, L"vol_internal.icns", 32 },
+   { NULL, L"vol_external.icns", 32 },
+   { NULL, L"vol_optical.icns", 32 },
 };
 
 EG_IMAGE * BuiltinIcon(IN UINTN Id)
 {
+    CHAR16 FileName[256];
+
     if (Id >= BUILTIN_ICON_COUNT)
         return NULL;
 
-    if (BuiltinIconTable[Id].Image == NULL)
-        BuiltinIconTable[Id].Image = LoadIcnsFallback(SelfDir, BuiltinIconTable[Id].Path, BuiltinIconTable[Id].PixelSize);
+    if (BuiltinIconTable[Id].Image == NULL) {
+        SPrint(FileName, 255, L"%s\\%s", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+               BuiltinIconTable[Id].FileName);
+        BuiltinIconTable[Id].Image = LoadIcnsFallback(SelfDir, FileName, BuiltinIconTable[Id].PixelSize);
+    } // if
 
     return BuiltinIconTable[Id].Image;
 }
@@ -90,7 +95,8 @@ EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconNam
 
     // try the names from OSIconName
     while ((CutoutName = FindCommaDelimited(OSIconName, Index++)) != NULL) {
-        SPrint(FileName, 255, L"icons\\%s_%s.icns", BootLogo ? L"boot" : L"os", CutoutName);
+       SPrint(FileName, 255, L"%s\\%s_%s.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+              BootLogo ? L"boot" : L"os", CutoutName);
 
         // try to load it
         Image = egLoadIcon(SelfDir, FileName, 128);
@@ -100,7 +106,8 @@ EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconNam
     } // while
 
     // try the fallback name
-    SPrint(FileName, 255, L"icons\\%s_%s.icns", BootLogo ? L"boot" : L"os", FallbackIconName);
+    SPrint(FileName, 255, L"%s\\%s_%s.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR,
+           BootLogo ? L"boot" : L"os", FallbackIconName);
     Image = egLoadIcon(SelfDir, FileName, 128);
     if (Image != NULL)
         return Image;
index 8b63c227a12c88e926b2a0fe648fac05f330527a..9f1cb4ebf9e9155a3311f931016fa74daee3c9cf 100644 (file)
@@ -83,6 +83,7 @@ VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DE
 VOID ScanVolumes(VOID);
 
 BOOLEAN FileExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath);
+BOOLEAN DirectoryExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath);
 
 EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, IN UINTN FilterMode);
 
index 8c4a78e683479c775266bb3516d1057e8b7da409..55ddf895b9252a3448df0639accedc4ba7f4335f 100644 (file)
@@ -85,7 +85,7 @@ static REFIT_MENU_ENTRY MenuEntryExit     = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0,
 static REFIT_MENU_SCREEN MainMenu       = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot" };
 static REFIT_MENU_SCREEN AboutMenu      = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL };
 
-REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 20, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
+REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 20, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                               {TAG_SHELL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }};
 
 // Structure used to hold boot loader filenames and time stamps in
@@ -104,7 +104,7 @@ static VOID AboutrEFInd(VOID)
 {
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
-        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.3.3.1");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.3.3.2");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
@@ -273,8 +273,8 @@ static CHAR16 * FindInitrd(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
    while ((DirIterNext(&DirIter, 2, L"init*", &DirEntry)) && (InitrdName == NULL)) {
       InitrdVersion = FindNumbers(DirEntry->FileName);
       if (KernelVersion != NULL) {
-            if (StriCmp(InitrdVersion, KernelVersion) == 0)
-               InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName);
+         if (StriCmp(InitrdVersion, KernelVersion) == 0)
+            InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName);
       } else {
          if (InitrdVersion == NULL)
             InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName);
index ad8d39c05926ac21ba58d1befe5ccaaa219ef051..24b5526aad52dedf59e67171bc9aa31b26fdccdb 100644 (file)
@@ -85,9 +85,6 @@ static EG_IMAGE *SelectionImages[4] = { NULL, NULL, NULL, NULL };
 static EG_PIXEL SelectionBackgroundPixel = { 0xff, 0xff, 0xff, 0 };
 static EG_IMAGE *TextBuffer = NULL;
 
-// Used in MainMenuStyle(), but must be persistent....
-UINTN row0PosX = 0, row0PosXRunning = 0, row1PosY = 0, row0Loaders = 0;
-
 //
 // Graphics helper functions
 //
@@ -180,7 +177,7 @@ static VOID InitScroll(OUT SCROLL_STATE *State, IN UINTN ItemCount, IN UINTN Vis
 
 // Adjust variables relating to the scrolling of tags, for when a selected icon isn't
 // visible given the current scrolling condition....
-static VOID AdjustScrollState(/* IN REFIT_MENU_SCREEN *Screen, */ IN SCROLL_STATE *State) {
+static VOID AdjustScrollState(IN SCROLL_STATE *State) {
    if (State->CurrentSelection > State->LastVisible) {
       State->LastVisible = State->CurrentSelection;
       State->FirstVisible = 1 + State->CurrentSelection - State->MaxVisible;
@@ -295,7 +292,7 @@ static VOID UpdateScroll(IN OUT SCROLL_STATE *State, IN UINTN Movement)
     if (!State->PaintAll && State->CurrentSelection != State->PreviousSelection)
         State->PaintSelection = TRUE;
     State->LastVisible = State->FirstVisible + State->MaxVisible - 1;
-}
+} // static VOID UpdateScroll()
 
 //
 // menu helper functions
@@ -772,7 +769,7 @@ static VOID PaintSelection(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
                            UINTN row0PosY, UINTN row1PosY, UINTN textPosY) {
    UINTN XSelectPrev, XSelectCur, YPosPrev, YPosCur;
 
-   if (((State->CurrentSelection < State->LastVisible) && (State->CurrentSelection >= State->FirstVisible)) ||
+   if (((State->CurrentSelection <= State->LastVisible) && (State->CurrentSelection >= State->FirstVisible)) ||
        (State->CurrentSelection >= State->InitialRow1) ) {
       if (Screen->Entries[State->PreviousSelection]->Row == 0) {
          XSelectPrev = State->PreviousSelection - State->FirstVisible;
@@ -822,10 +819,11 @@ static VOID PaintIcon(IN EG_EMBEDDED_IMAGE *BuiltInIcon, IN CHAR16 *ExternalFile
 VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText)
 {
     INTN i;
-    extern UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders;
+    static UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders;
     UINTN row0Count, row1Count, row1PosX, row1PosXRunning;
     static UINTN *itemPosX;
     static UINTN row0PosY, textPosY;
+    CHAR16 FileName[256];
 
     State->ScrollMode = SCROLL_MODE_ICONS;
     switch (Function) {
@@ -882,13 +880,17 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT
             // For PaintIcon() calls, the starting Y position is moved to the midpoint
             // of the surrounding row; PaintIcon() adjusts this back up by half the
             // icon's height to properly center it.
-            if ((State->FirstVisible > 0) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS)))
-               PaintIcon(&egemb_arrow_left, L"icons\\arrow_left.icns", row0PosX - TILE_XSPACING,
+            if ((State->FirstVisible > 0) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS))) {
+               SPrint(FileName, 255, L"%s\\arrow_left.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR);
+               PaintIcon(&egemb_arrow_left, FileName, row0PosX - TILE_XSPACING,
                          row0PosY + (ROW0_TILESIZE / 2), ALIGN_RIGHT);
-            if ((State->LastVisible < (row0Loaders - 1)) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS)))
-               PaintIcon(&egemb_arrow_right, L"icons\\arrow_right.icns",
+            } // if
+            if ((State->LastVisible < (row0Loaders - 1)) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS))) {
+               SPrint(FileName, 255, L"%s\\arrow_left.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR);
+               PaintIcon(&egemb_arrow_right, FileName,
                          (UGAWidth + (ROW0_TILESIZE + TILE_XSPACING) * State->MaxVisible) / 2 + TILE_XSPACING,
                          row0PosY + (ROW0_TILESIZE / 2), ALIGN_LEFT);
+            } // if
             break;
 
         case MENU_FUNCTION_PAINT_SELECTION: