Repository: ghaerr/elks
Pull request #2283: Paint add flood fill button
Author: login: Vutshi
Created: 2025-04-06T21:29:27Z | Merged: 2025-04-06T21:55:27Z

- Add flood fill button
- rename SCREEN_WIDTH to CANVAS_WIDTH
- automated buttons generation code

TODO: add indication of brush/fill either in icons (XOR it?) or in cursor

<img width="752" alt="paint_fill_new" src="https://github.com/user-attachments/assets/ac2d8596-bdfb-456b-b11b-3e32fcb750b0" />



Diff:
diff --git a/elkscmd/Applications b/elkscmd/Applications
index 4727ffdfc..eab2bc6d6 100644
--- a/elkscmd/Applications
+++ b/elkscmd/Applications
@@ -186,6 +186,8 @@ gui/images/cls.bmp  ::lib/cls.bmp   :gui                        :1440k
 gui/images/save.bmp ::lib/save.bmp  :gui                        :1440k
 gui/images/quit.bmp ::lib/quit.bmp  :gui                        :1440k
 gui/images/paint.bmp ::lib/paint.bmp  :gui                        :1440k
+gui/images/fill.bmp ::lib/fill.bmp  :gui                        :1440k
+gui/images/brush.bmp ::lib/brush.bmp  :gui                      :1440k
 busyelks/busyelks               :busyelks
 inet/httpd/sample_index.html ::var/www/index.html :net
 ktcp/ktcp                       :net
diff --git a/elkscmd/gui/app.c b/elkscmd/gui/app.c
index dbec4bca4..6cfefb8cc 100644
--- a/elkscmd/gui/app.c
+++ b/elkscmd/gui/app.c
@@ -14,6 +14,7 @@ app_t DrawingApp;
 
 boolean_t drawing;              // Are we drawing with the left mouse button?
 boolean_t altdrawing;           // Are we drawing with the right mouse button?
+boolean_t floodFill;            // Are we flood filling with the left mouse button?
 boolean_t floodFillCalled;      // True if user is trying to floodfill
 int mx,my;                      // Mouse X and Y
 int omx, omy;                   // Old MouseX and Old MouseY (pos at previous update)
@@ -38,10 +39,7 @@ void A_InitTomentPainter(void)
     graphics_open(EGA? VGA_640x350x16: VGA_640x480x16);
 
     DrawingApp.quit = false;
-
-    // for(int y = 0; y < SCREEN_HEIGHT; y++)
-    //     for(int x = 0; x < SCREEN_WIDTH; x++)
-    //         drawpixel(x, y, BLACK);
+    floodFill = false;
 
     A_InitPalette();
 }
@@ -61,132 +59,81 @@ void A_InitPalette(void)
 
 
     // Create and configure buttons
-#if UNUSED
-    paletteButtons[0].name = "BrightnessSelector";
-    paletteButtons[0].box.x = 775;
-    paletteButtons[0].box.y = 10;
-    paletteButtons[0].box.w = 16;
-    paletteButtons[0].box.h = 64;
-    paletteButtons[0].OnClick = G_BrightnessButtonOnClick;
-    paletteButtons[0].render = false;
-#endif
-    paletteButtons[1].name = "ColorPicker";
-    paletteButtons[1].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[1].box.y = 10;
-    paletteButtons[1].box.w = 128;
-    paletteButtons[1].box.h = 128;
-    paletteButtons[1].OnClick = G_ColorPickerOnClick;
-    paletteButtons[1].render = false;
-
-    // Bush Sizes 1
-    paletteButtons[2].name = "BushSize1";
-    paletteButtons[2].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[2].box.y = 195;
-    paletteButtons[2].box.w = 30;
-    paletteButtons[2].box.h = 30;
-    paletteButtons[2].OnClick = G_SetBushSize;
-    paletteButtons[2].data1 = 1;
-    paletteButtons[2].render = true;
-
-    // Bush Sizes 2
-    paletteButtons[3].name = "BushSize2";
-    paletteButtons[3].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[3].box.y = 195;
-    paletteButtons[3].box.w = 30;
-    paletteButtons[3].box.h = 30;
-    paletteButtons[3].OnClick = G_SetBushSize;
-    paletteButtons[3].data1 = 2;
-    paletteButtons[3].render = true;
-
-    // Bush Sizes 3
-    paletteButtons[4].name = "BushSize3";
-    paletteButtons[4].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[4].box.y = 195;
-    paletteButtons[4].box.w = 30;
-    paletteButtons[4].box.h = 30;
-    paletteButtons[4].OnClick = G_SetBushSize;
-    paletteButtons[4].data1 = 3;
-    paletteButtons[4].render = true;
-
-    // Bush Sizes 4
-    paletteButtons[5].name = "BushSize4";
-    paletteButtons[5].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[5].box.y = 195;
-    paletteButtons[5].box.w = 30;
-    paletteButtons[5].box.h = 30;
-    paletteButtons[5].OnClick = G_SetBushSize;
-    paletteButtons[5].data1 = 4;
-    paletteButtons[5].render = true;
-
-    // Bush Sizes 5
-    paletteButtons[6].name = "BushSize5";
-    paletteButtons[6].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[6].box.y = 227;
-    paletteButtons[6].box.w = 30;
-    paletteButtons[6].box.h = 30;
-    paletteButtons[6].OnClick = G_SetBushSize;
-    paletteButtons[6].data1 = 6;
-    paletteButtons[6].render = true;
-
-    // Bush Sizes 6
-    paletteButtons[7].name = "BushSize6";
-    paletteButtons[7].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[7].box.y = 227;
-    paletteButtons[7].box.w = 30;
-    paletteButtons[7].box.h = 30;
-    paletteButtons[7].OnClick = G_SetBushSize;
-    paletteButtons[7].data1 = 8;
-    paletteButtons[7].render = true;
-
-    // Bush Sizes 7
-    paletteButtons[8].name = "BushSize7";
-    paletteButtons[8].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[8].box.y = 227;
-    paletteButtons[8].box.w = 30;
-    paletteButtons[8].box.h = 30;
-    paletteButtons[8].OnClick = G_SetBushSize;
-    paletteButtons[8].data1 = 10;
-    paletteButtons[8].render = true;
-
-    // Bush Sizes 8
-    paletteButtons[9].name = "BushSize8";
-    paletteButtons[9].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[9].box.y = 227;
-    paletteButtons[9].box.w = 30;
-    paletteButtons[9].box.h = 30;
-    paletteButtons[9].OnClick = G_SetBushSize;
-    paletteButtons[9].data1 = 12;
-    paletteButtons[9].render = true;
-
-    // Save
-    paletteButtons[10].name = "SaveButton";
-    paletteButtons[10].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[10].box.y = 300;
-    paletteButtons[10].box.w = 32;
-    paletteButtons[10].box.h = 32;
-    paletteButtons[10].OnClick = G_SaveButtonOnClick;
-    paletteButtons[10].render = true;
-    paletteButtons[10].fileName = LIBPATH "save.bmp";
-
-    // Clear Screen
-    paletteButtons[11].name = "Cls";
-    paletteButtons[11].box.x = SCREEN_WIDTH + 10 + 32*2;
-    paletteButtons[11].box.y = 300;
-    paletteButtons[11].box.w = 32;
-    paletteButtons[11].box.h = 32;
-    paletteButtons[11].OnClick = G_ClearScreen;
-    paletteButtons[11].render = true;
-    paletteButtons[11].fileName = LIBPATH "cls.bmp";
-
-    // Quit
-    paletteButtons[12].name = "QuitButton";
-    paletteButtons[12].box.x = SCREEN_WIDTH + 10 + 32*3;
-    paletteButtons[12].box.y = 300;
-    paletteButtons[12].box.w = 32;
-    paletteButtons[12].box.h = 32;
-    paletteButtons[12].OnClick = G_QuitButtonOnClick;
-    paletteButtons[12].render = true;
-    paletteButtons[12].fileName = LIBPATH "quit.bmp";
+    // --- Helper macro to initialize buttons ---
+#define INIT_BUTTON(ID, LABEL, X, Y, W, H, CLICK, RENDER) \
+    paletteButtons[ID].name = LABEL; \
+    paletteButtons[ID].box.x = (X); \
+    paletteButtons[ID].box.y = (Y); \
+    paletteButtons[ID].box.w = (W); \
+    paletteButtons[ID].box.h = (H); \
+    paletteButtons[ID].OnClick = CLICK; \
+    paletteButtons[ID].render = RENDER;
+
+    #if UNUSED
+        INIT_BUTTON(0, "BrightnessSelector", 775, 10, 16, 64, G_BrightnessButtonOnClick, 0);
+    #endif
+
+    // --- Color Picker ---
+    INIT_BUTTON(1, "ColorPicker", CANVAS_WIDTH + 10, 10, 128, 128, G_ColorPickerOnClick, 0);
+
+    // --- Brush Size Buttons (8 total in two rows) ---
+    {
+        int brushSizes[8] = {1, 2, 3, 4,
+                                   6, 8, 10, 12};
+        char* brushNames[8] = {
+            "BushSize1", "BushSize2", "BushSize3", "BushSize4",
+            "BushSize5", "BushSize6", "BushSize7", "BushSize8"
+        };
+
+        for (int i = 0; i < 8; ++i) {
+            int index = i + 2;
+            int col = i % 4;
+            int row = i / 4;
+            INIT_BUTTON(index,
+                        brushNames[i],
+                        CANVAS_WIDTH + 11 + 32 * col,
+                        195 + row * 32,
+                        30, 30,
+                        G_SetBushSize, 1);
+            paletteButtons[index].data1 = brushSizes[i];
+        }
+    }
+
+    // --- Utility Buttons ---
+    {
+        int utilCount = 5;
+        int indices[]   = {10, 11, 12, 13, 14};
+        char* names[]   = {"SaveButton", "FillButton", "BrushButton", "QuitButton", "Cls"};
+        int offsetX[]   = {0,  32,   0, 32 * 3, 32 * 3};
+        int offsetY[]   = {0, -32, -32,      0,    -32};
+        int (*handlers[])(struct button_s*) = {
+            G_SaveButtonOnClick,
+            G_SetFloodFill,
+            G_SetBrush,
+            G_QuitButtonOnClick,
+            G_ClearScreen
+        };
+        char* files[] = {
+            LIBPATH "save.bmp",
+            LIBPATH "fill.bmp",
+            LIBPATH "brush.bmp",
+            LIBPATH "quit.bmp",
+            LIBPATH "cls.bmp"
+        };
+
+        for (int i = 0; i < utilCount; ++i) {
+            INIT_BUTTON(indices[i],
+                        names[i],
+                        CANVAS_WIDTH + 10 + offsetX[i],
+                        300 + offsetY[i],
+                        32, 32,
+                        handlers[i],
+                        1);
+            paletteButtons[indices[i]].fileName = files[i];
+        }
+    }
+
+#undef INIT_BUTTON
 }
 
 
@@ -197,10 +144,10 @@ void A_GameLoop(void)
 {
     movecursor(mx, my);
 
-    if((drawing || altdrawing) && mx > SCREEN_WIDTH) mx = SCREEN_WIDTH;
+    if((drawing || altdrawing) && mx > CANVAS_WIDTH) mx = CANVAS_WIDTH;
 
     // In canvas
-    if(mx <= SCREEN_WIDTH)
+    if(mx <= CANVAS_WIDTH)
     {
         mouseOnPalette = false;
 
diff --git a/elkscmd/gui/app.h b/elkscmd/gui/app.h
index f94a82252..2b3e258c4 100644
--- a/elkscmd/gui/app.h
+++ b/elkscmd/gui/app.h
@@ -2,8 +2,8 @@
 #define APPLICATION_H_INCLUDED
 
 // Drawing + Palette
-#define SCREEN_WIDTH    (SCREENWIDTH-PALETTE_WIDTH)
-#define SCREEN_HEIGHT   SCREENHEIGHT
+#define CANVAS_WIDTH    (SCREENWIDTH-PALETTE_WIDTH)
+#define CANVAS_HEIGHT   SCREENHEIGHT
 
 #define PALETTE_WIDTH 148
 
@@ -60,7 +60,8 @@ extern app_t DrawingApp;
 
 extern boolean_t drawing;              // Are we drawing with the left mouse button?
 extern boolean_t altdrawing;           // Are we drawing with the right mouse button?
-extern boolean_t floodFillCalled;      // True if user is trying to flood fiil
+extern boolean_t floodFill;            // Are we flood filling with the left mouse button?
+extern boolean_t floodFillCalled;      // True if user is trying to flood fill
 extern int mx,my;                      // Mouse X and Y
 extern int omx, omy;                   // Old MouseX and MouseY (pos at previous update)
 extern boolean_t mouseOnPalette;       // True if the mouse is on the palette and not the canvas
@@ -71,7 +72,7 @@ extern int currentMainColor;           // The selected color for LMB
 extern int currentAltColor;            // Color for RMB (eraser)
 
 // Palette Buttons
-#define PALETTE_BUTTONS_COUNT 13 //14
+#define PALETTE_BUTTONS_COUNT 15
 
 // All the buttons
 extern button_t paletteButtons[PALETTE_BUTTONS_COUNT];
diff --git a/elkscmd/gui/drawbmp.c b/elkscmd/gui/drawbmp.c
index a81b1553b..0460896d4 100644
--- a/elkscmd/gui/drawbmp.c
+++ b/elkscmd/gui/drawbmp.c
@@ -319,7 +319,7 @@ draw_bmp(char *path, int x, int y)
     }
     fclose(src);
     return 1;
-    
+
 out:
     fclose(src);
 err:
@@ -469,8 +469,8 @@ int save_bmp(char *pathname)
     if (!ofp)
         return 1;
 
-    cx = SCREEN_WIDTH;
-    cy = SCREEN_HEIGHT;
+    cx = CANVAS_WIDTH;
+    cy = CANVAS_HEIGHT;
     bpp = 8;                /* write 8bpp for now */
     ncolors = (bpp <= 8)? 16: 0;
     bytespp = (bpp+7)/8;
diff --git a/elkscmd/gui/gui.c b/elkscmd/gui/gui.c
index 0d055e5d4..bdb3999ea 100644
--- a/elkscmd/gui/gui.c
+++ b/elkscmd/gui/gui.c
@@ -50,3 +50,15 @@ int G_ClearScreen(struct button_s* btn)
     R_ClearCanvas();
     return 0;
 }
+
+int G_SetFloodFill(struct button_s* btn)
+{
+    floodFill = true;
+    return 0;
+}
+
+int G_SetBrush(struct button_s* btn)
+{
+    floodFill = false;
+    return 0;
+}
diff --git a/elkscmd/gui/gui.h b/elkscmd/gui/gui.h
index 65c30c390..97183e424 100644
--- a/elkscmd/gui/gui.h
+++ b/elkscmd/gui/gui.h
@@ -11,5 +11,8 @@ int G_SaveButtonOnClick(struct button_s* btn);
 int G_QuitButtonOnClick(struct button_s* btn);
 int G_SetBushSize(struct button_s* btn);
 int G_ClearScreen(struct button_s* btn);
+int G_SetFloodFill(struct button_s* btn);
+int G_SetBrush(struct button_s* btn);
+
 
 #endif
diff --git a/elkscmd/gui/images/brush.bmp b/elkscmd/gui/images/brush.bmp
new file mode 100644
index 000000000..2f5814123
Binary files /dev/null and b/elkscmd/gui/images/brush.bmp differ
diff --git a/elkscmd/gui/images/fill.bmp b/elkscmd/gui/images/fill.bmp
new file mode 100644
index 000000000..96c5707c6
Binary files /dev/null and b/elkscmd/gui/images/fill.bmp differ
diff --git a/elkscmd/gui/input.c b/elkscmd/gui/input.c
index fa8352936..2d1ad9d25 100644
--- a/elkscmd/gui/input.c
+++ b/elkscmd/gui/input.c
@@ -31,11 +31,15 @@ void I_HandleInput(void)
 
                 mx = event.x;
                 my = event.y;
-                if (mx < SCREEN_WIDTH){
-                    if(event.button == BUTTON_L)
-                        drawing = true;
-                    else
-                        altdrawing = true;
+                if (mx < CANVAS_WIDTH){
+                    if(floodFill) {
+                        floodFillCalled = true;
+                    } else {
+                            if(event.button == BUTTON_L)
+                                drawing = true;
+                            else
+                                altdrawing = true;
+                        }
                 }
                 hidecursor();
 
@@ -133,11 +137,11 @@ void I_HandleInput(void)
     my = posy;
 
 #if UNUSED
-    mx = CLAMP(mx, 0, SCREEN_WIDTH + PALETTE_WIDTH);
-    my = CLAMP(my, 0, SCREEN_HEIGHT-1);
+    mx = CLAMP(mx, 0, CANVAS_WIDTH + PALETTE_WIDTH);
+    my = CLAMP(my, 0, CANVAS_HEIGHT-1);
 
-    omx = CLAMP(omx, 0, SCREEN_WIDTH + PALETTE_WIDTH);
-    omy = CLAMP(omy, 0, SCREEN_HEIGHT-1);
+    omx = CLAMP(omx, 0, CANVAS_WIDTH + PALETTE_WIDTH);
+    omy = CLAMP(omy, 0, CANVAS_HEIGHT-1);
 #endif
 }
 
diff --git a/elkscmd/gui/render.c b/elkscmd/gui/render.c
index b2920f84f..0328703b3 100644
--- a/elkscmd/gui/render.c
+++ b/elkscmd/gui/render.c
@@ -1,7 +1,6 @@
 #include <stdlib.h>
 #include "app.h"
 #include "render.h"
-// #include "event.h"
 #include "graphics.h"
 
 #define FLOOD_FILL_STACK    100
@@ -11,7 +10,7 @@
 // ----------------------------------------------------
 void R_ClearCanvas(void)
 {
-    fillrect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-1, BLACK);
+    fillrect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT-1, BLACK);
 }
 
 
@@ -21,16 +20,16 @@ void R_ClearCanvas(void)
 void R_DrawPalette()
 {
     // Draw line and background
-    drawvline(SCREEN_WIDTH+1, 0, SCREEN_HEIGHT-1, WHITE);
-    fillrect(SCREEN_WIDTH + 2, 0,
-        SCREEN_WIDTH + PALETTE_WIDTH - 1, SCREEN_HEIGHT - 1, GRAY);
+    drawvline(CANVAS_WIDTH+1, 0, CANVAS_HEIGHT-1, WHITE);
+    fillrect(CANVAS_WIDTH + 2, 0,
+        CANVAS_WIDTH + PALETTE_WIDTH - 1, CANVAS_HEIGHT - 1, GRAY);
 
     R_UpdateColorPicker();
     R_DrawAllButtons();
 
     // Draw Logo if VGA 640x480
-    if(SCREEN_HEIGHT == 480)
-        draw_bmp(LIBPATH "paint.bmp", SCREEN_WIDTH + 10, 350);
+    if(CANVAS_HEIGHT == 480)
+        draw_bmp(LIBPATH "paint.bmp", CANVAS_WIDTH + 10, 350);
 }
 
 // ----------------------------------------------------
@@ -76,7 +75,7 @@ static int MapRGB(int r, int g, int b)
 void R_UpdateColorPicker(void)
 {
     // Draw RGB scheme
-    int startingPixelXOffset = SCREEN_WIDTH + 10 + 1;
+    int startingPixelXOffset = CANVAS_WIDTH + 10 + 1;
     int startingPixelYOffset = 10 + 1;
 
     //static ColorRGB_t color;
@@ -103,7 +102,7 @@ void R_UpdateColorPicker(void)
 void R_DrawCurrentColor(void)
 {
     // Draw current color
-    int startingPixelXOffset = SCREEN_WIDTH + 10 + 32 + 1;
+    int startingPixelXOffset = CANVAS_WIDTH + 10 + 32 + 1;
     int startingPixelYOffset = 10 + 128 + 10;
 
     fillrect(startingPixelXOffset, startingPixelYOffset, startingPixelXOffset + 61,
@@ -124,7 +123,7 @@ void R_DrawCurrentColor(void)
 void R_Paint(int x1, int y1, int x2, int y2) {
     int color = drawing ? currentMainColor : currentAltColor;
     // Draw initial point
-    R_DrawDisk(x1, y1, bushSize, color, SCREEN_WIDTH);
+    R_DrawDisk(x1, y1, bushSize, color, CANVAS_WIDTH);
 
     // Bresenham's line algorithm for efficient line drawing
     int dx = abs(x2 - x1);
@@ -134,7 +133,7 @@ void R_Paint(int x1, int y1, int x2, int y2) {
     int err = dx - dy;
 
     while (x1 != x2 || y1 != y2) {
-        R_DrawDisk(x1, y1, bushSize, color, SCREEN_WIDTH);
+        R_DrawDisk(x1, y1, bushSize, color, CANVAS_WIDTH);
 
         int e2 = err << 1;
         if (e2 > -dy) {
@@ -163,7 +162,7 @@ void R_DrawDisk(int x0, int y0, int r, int color, int X_lim)
         int xstart = (x0 + x >= 0) ? x0 + x : 0;
         int xend   = (x0 - x <= X_lim) ? x0 - x : X_lim;
 
-        if (y0 + y < SCREEN_HEIGHT)
+        if (y0 + y < CANVAS_HEIGHT)
             drawhline(xstart, xend, y0 + y, color);
 
         if (y0 - y >= 0 && y > 0)
@@ -233,14 +232,14 @@ void R_LineFloodFill(int x, int y, int color, int ogColor)
         while(mRight == false)
         {
             // Fill right
-            if(leftestX < SCREEN_WIDTH && readpixel(leftestX, curElement.y) == ogColor)
+            if(leftestX < CANVAS_WIDTH && readpixel(leftestX, curElement.y) == ogColor)
             {
                 //pixels[leftestX + curElement.y * width] = color;
                 drawpixel(leftestX, curElement.y, color);
 
                 // Check above this pixel
                 if (alreadyCheckedBelow == false && (curElement.y-1) >= 0
-                    && (curElement.y-1) < SCREEN_HEIGHT
+                    && (curElement.y-1) < CANVAS_HEIGHT
                     && readpixel(leftestX, curElement.y-1) == ogColor)
                     {
                         // If we never checked it, add it to the stack
@@ -256,7 +255,7 @@ void R_LineFloodFill(int x, int y, int color, int ogColor)
 
                 // Check below this pixel
                 if (alreadyCheckedAbove == false && (curElement.y+1) >= 0
-                    && (curElement.y+1) < SCREEN_HEIGHT
+                    && (curElement.y+1) < CANVAS_HEIGHT
                     && readpixel(leftestX, curElement.y+1) == ogColor)
                     {
                         // If we never checked it, add it to the stack
@@ -264,7 +263,7 @@ void R_LineFloodFill(int x, int y, int color, int ogColor)
                         alreadyCheckedAbove = true;
                     }
                 else if (alreadyCheckedAbove == true
-                    && (curElement.y+1) < SCREEN_WIDTH
+                    && (curElement.y+1) < CANVAS_WIDTH
                     && readpixel(leftestX, curElement.y+1) != ogColor)
                 {
                     // Skip now, but check next time


Reviews:
user: login: ghaerr
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-06T22:00:35Z
user: login: Vutshi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-06T22:07:43Z
user: login: ghaerr
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-06T22:15:36Z

Review comments:
diff_hunk: @@ -61,132 +59,81 @@ void A_InitPalette(void)
 
 
     // Create and configure buttons
-#if UNUSED
-    paletteButtons[0].name = "BrightnessSelector";
-    paletteButtons[0].box.x = 775;
-    paletteButtons[0].box.y = 10;
-    paletteButtons[0].box.w = 16;
-    paletteButtons[0].box.h = 64;
-    paletteButtons[0].OnClick = G_BrightnessButtonOnClick;
-    paletteButtons[0].render = false;
-#endif
-    paletteButtons[1].name = "ColorPicker";
-    paletteButtons[1].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[1].box.y = 10;
-    paletteButtons[1].box.w = 128;
-    paletteButtons[1].box.h = 128;
-    paletteButtons[1].OnClick = G_ColorPickerOnClick;
-    paletteButtons[1].render = false;
-
-    // Bush Sizes 1
-    paletteButtons[2].name = "BushSize1";
-    paletteButtons[2].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[2].box.y = 195;
-    paletteButtons[2].box.w = 30;
-    paletteButtons[2].box.h = 30;
-    paletteButtons[2].OnClick = G_SetBushSize;
-    paletteButtons[2].data1 = 1;
-    paletteButtons[2].render = true;
-
-    // Bush Sizes 2
-    paletteButtons[3].name = "BushSize2";
-    paletteButtons[3].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[3].box.y = 195;
-    paletteButtons[3].box.w = 30;
-    paletteButtons[3].box.h = 30;
-    paletteButtons[3].OnClick = G_SetBushSize;
-    paletteButtons[3].data1 = 2;
-    paletteButtons[3].render = true;
-
-    // Bush Sizes 3
-    paletteButtons[4].name = "BushSize3";
-    paletteButtons[4].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[4].box.y = 195;
-    paletteButtons[4].box.w = 30;
-    paletteButtons[4].box.h = 30;
-    paletteButtons[4].OnClick = G_SetBushSize;
-    paletteButtons[4].data1 = 3;
-    paletteButtons[4].render = true;
-
-    // Bush Sizes 4
-    paletteButtons[5].name = "BushSize4";
-    paletteButtons[5].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[5].box.y = 195;
-    paletteButtons[5].box.w = 30;
-    paletteButtons[5].box.h = 30;
-    paletteButtons[5].OnClick = G_SetBushSize;
-    paletteButtons[5].data1 = 4;
-    paletteButtons[5].render = true;
-
-    // Bush Sizes 5
-    paletteButtons[6].name = "BushSize5";
-    paletteButtons[6].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[6].box.y = 227;
-    paletteButtons[6].box.w = 30;
-    paletteButtons[6].box.h = 30;
-    paletteButtons[6].OnClick = G_SetBushSize;
-    paletteButtons[6].data1 = 6;
-    paletteButtons[6].render = true;
-
-    // Bush Sizes 6
-    paletteButtons[7].name = "BushSize6";
-    paletteButtons[7].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[7].box.y = 227;
-    paletteButtons[7].box.w = 30;
-    paletteButtons[7].box.h = 30;
-    paletteButtons[7].OnClick = G_SetBushSize;
-    paletteButtons[7].data1 = 8;
-    paletteButtons[7].render = true;
-
-    // Bush Sizes 7
-    paletteButtons[8].name = "BushSize7";
-    paletteButtons[8].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[8].box.y = 227;
-    paletteButtons[8].box.w = 30;
-    paletteButtons[8].box.h = 30;
-    paletteButtons[8].OnClick = G_SetBushSize;
-    paletteButtons[8].data1 = 10;
-    paletteButtons[8].render = true;
-
-    // Bush Sizes 8
-    paletteButtons[9].name = "BushSize8";
-    paletteButtons[9].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[9].box.y = 227;
-    paletteButtons[9].box.w = 30;
-    paletteButtons[9].box.h = 30;
-    paletteButtons[9].OnClick = G_SetBushSize;
-    paletteButtons[9].data1 = 12;
-    paletteButtons[9].render = true;
-
-    // Save
-    paletteButtons[10].name = "SaveButton";
-    paletteButtons[10].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[10].box.y = 300;
-    paletteButtons[10].box.w = 32;
-    paletteButtons[10].box.h = 32;
-    paletteButtons[10].OnClick = G_SaveButtonOnClick;
-    paletteButtons[10].render = true;
-    paletteButtons[10].fileName = LIBPATH "save.bmp";
-
-    // Clear Screen
-    paletteButtons[11].name = "Cls";
-    paletteButtons[11].box.x = SCREEN_WIDTH + 10 + 32*2;
-    paletteButtons[11].box.y = 300;
-    paletteButtons[11].box.w = 32;
-    paletteButtons[11].box.h = 32;
-    paletteButtons[11].OnClick = G_ClearScreen;
-    paletteButtons[11].render = true;
-    paletteButtons[11].fileName = LIBPATH "cls.bmp";
-
-    // Quit
-    paletteButtons[12].name = "QuitButton";
-    paletteButtons[12].box.x = SCREEN_WIDTH + 10 + 32*3;
-    paletteButtons[12].box.y = 300;
-    paletteButtons[12].box.w = 32;
-    paletteButtons[12].box.h = 32;
-    paletteButtons[12].OnClick = G_QuitButtonOnClick;
-    paletteButtons[12].render = true;
-    paletteButtons[12].fileName = LIBPATH "quit.bmp";
+    // --- Helper macro to initialize buttons ---
+#define INIT_BUTTON(ID, LABEL, X, Y, W, H, CLICK, RENDER) \
+    paletteButtons[ID].name = LABEL; \
+    paletteButtons[ID].box.x = (X); \
+    paletteButtons[ID].box.y = (Y); \
+    paletteButtons[ID].box.w = (W); \
+    paletteButtons[ID].box.h = (H); \
+    paletteButtons[ID].OnClick = CLICK; \
+    paletteButtons[ID].render = RENDER;
+
+    #if UNUSED
+        INIT_BUTTON(0, "BrightnessSelector", 775, 10, 16, 64, G_BrightnessButtonOnClick, 0);
+    #endif
+
+    // --- Color Picker ---
+    INIT_BUTTON(1, "ColorPicker", CANVAS_WIDTH + 10, 10, 128, 128, G_ColorPickerOnClick, 0);
+
+    // --- Brush Size Buttons (8 total in two rows) ---
+    {
+        int brushSizes[8] = {1, 2, 3, 4,
+                                   6, 8, 10, 12};
+        char* brushNames[8] = {
+            "BushSize1", "BushSize2", "BushSize3", "BushSize4",
+            "BushSize5", "BushSize6", "BushSize7", "BushSize8"
+        };
+
+        for (int i = 0; i < 8; ++i) {
+            int index = i + 2;
+            int col = i % 4;
+            int row = i / 4;
+            INIT_BUTTON(index,
+                        brushNames[i],
+                        CANVAS_WIDTH + 11 + 32 * col,
+                        195 + row * 32,
+                        30, 30,
+                        G_SetBushSize, 1);
+            paletteButtons[index].data1 = brushSizes[i];
+        }
+    }
+
+    // --- Utility Buttons ---
+    {
+        int utilCount = 5;
+        int indices[]   = {10, 11, 12, 13, 14};
+        char* names[]   = {"SaveButton", "FillButton", "BrushButton", "QuitButton", "Cls"};
+        int offsetX[]   = {0,  32,   0, 32 * 3, 32 * 3};
+        int offsetY[]   = {0, -32, -32,      0,    -32};
path: elkscmd/gui/app.c
user: login: ghaerr
body: Are you aware how expensive this is, to declare auto initialized array variables? The initializations have to be saved in the data segment at compile time, but then at runtime copied via an internal call to memcpy to get them on the stack; IMO lots of extra code for nothing.

I recommend adding 'static' to the declarations which achieves the same result with lots less code. Same for the variables on lines 81-85.

(You can use `ia16-elf-objdump -D -r -Mi8086 app.oaj` to see code generated).
created_at: 2025-04-06T22:00:35Z
author_association: OWNER
diff_hunk: @@ -61,132 +59,81 @@ void A_InitPalette(void)
 
 
     // Create and configure buttons
-#if UNUSED
-    paletteButtons[0].name = "BrightnessSelector";
-    paletteButtons[0].box.x = 775;
-    paletteButtons[0].box.y = 10;
-    paletteButtons[0].box.w = 16;
-    paletteButtons[0].box.h = 64;
-    paletteButtons[0].OnClick = G_BrightnessButtonOnClick;
-    paletteButtons[0].render = false;
-#endif
-    paletteButtons[1].name = "ColorPicker";
-    paletteButtons[1].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[1].box.y = 10;
-    paletteButtons[1].box.w = 128;
-    paletteButtons[1].box.h = 128;
-    paletteButtons[1].OnClick = G_ColorPickerOnClick;
-    paletteButtons[1].render = false;
-
-    // Bush Sizes 1
-    paletteButtons[2].name = "BushSize1";
-    paletteButtons[2].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[2].box.y = 195;
-    paletteButtons[2].box.w = 30;
-    paletteButtons[2].box.h = 30;
-    paletteButtons[2].OnClick = G_SetBushSize;
-    paletteButtons[2].data1 = 1;
-    paletteButtons[2].render = true;
-
-    // Bush Sizes 2
-    paletteButtons[3].name = "BushSize2";
-    paletteButtons[3].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[3].box.y = 195;
-    paletteButtons[3].box.w = 30;
-    paletteButtons[3].box.h = 30;
-    paletteButtons[3].OnClick = G_SetBushSize;
-    paletteButtons[3].data1 = 2;
-    paletteButtons[3].render = true;
-
-    // Bush Sizes 3
-    paletteButtons[4].name = "BushSize3";
-    paletteButtons[4].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[4].box.y = 195;
-    paletteButtons[4].box.w = 30;
-    paletteButtons[4].box.h = 30;
-    paletteButtons[4].OnClick = G_SetBushSize;
-    paletteButtons[4].data1 = 3;
-    paletteButtons[4].render = true;
-
-    // Bush Sizes 4
-    paletteButtons[5].name = "BushSize4";
-    paletteButtons[5].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[5].box.y = 195;
-    paletteButtons[5].box.w = 30;
-    paletteButtons[5].box.h = 30;
-    paletteButtons[5].OnClick = G_SetBushSize;
-    paletteButtons[5].data1 = 4;
-    paletteButtons[5].render = true;
-
-    // Bush Sizes 5
-    paletteButtons[6].name = "BushSize5";
-    paletteButtons[6].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[6].box.y = 227;
-    paletteButtons[6].box.w = 30;
-    paletteButtons[6].box.h = 30;
-    paletteButtons[6].OnClick = G_SetBushSize;
-    paletteButtons[6].data1 = 6;
-    paletteButtons[6].render = true;
-
-    // Bush Sizes 6
-    paletteButtons[7].name = "BushSize6";
-    paletteButtons[7].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[7].box.y = 227;
-    paletteButtons[7].box.w = 30;
-    paletteButtons[7].box.h = 30;
-    paletteButtons[7].OnClick = G_SetBushSize;
-    paletteButtons[7].data1 = 8;
-    paletteButtons[7].render = true;
-
-    // Bush Sizes 7
-    paletteButtons[8].name = "BushSize7";
-    paletteButtons[8].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[8].box.y = 227;
-    paletteButtons[8].box.w = 30;
-    paletteButtons[8].box.h = 30;
-    paletteButtons[8].OnClick = G_SetBushSize;
-    paletteButtons[8].data1 = 10;
-    paletteButtons[8].render = true;
-
-    // Bush Sizes 8
-    paletteButtons[9].name = "BushSize8";
-    paletteButtons[9].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[9].box.y = 227;
-    paletteButtons[9].box.w = 30;
-    paletteButtons[9].box.h = 30;
-    paletteButtons[9].OnClick = G_SetBushSize;
-    paletteButtons[9].data1 = 12;
-    paletteButtons[9].render = true;
-
-    // Save
-    paletteButtons[10].name = "SaveButton";
-    paletteButtons[10].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[10].box.y = 300;
-    paletteButtons[10].box.w = 32;
-    paletteButtons[10].box.h = 32;
-    paletteButtons[10].OnClick = G_SaveButtonOnClick;
-    paletteButtons[10].render = true;
-    paletteButtons[10].fileName = LIBPATH "save.bmp";
-
-    // Clear Screen
-    paletteButtons[11].name = "Cls";
-    paletteButtons[11].box.x = SCREEN_WIDTH + 10 + 32*2;
-    paletteButtons[11].box.y = 300;
-    paletteButtons[11].box.w = 32;
-    paletteButtons[11].box.h = 32;
-    paletteButtons[11].OnClick = G_ClearScreen;
-    paletteButtons[11].render = true;
-    paletteButtons[11].fileName = LIBPATH "cls.bmp";
-
-    // Quit
-    paletteButtons[12].name = "QuitButton";
-    paletteButtons[12].box.x = SCREEN_WIDTH + 10 + 32*3;
-    paletteButtons[12].box.y = 300;
-    paletteButtons[12].box.w = 32;
-    paletteButtons[12].box.h = 32;
-    paletteButtons[12].OnClick = G_QuitButtonOnClick;
-    paletteButtons[12].render = true;
-    paletteButtons[12].fileName = LIBPATH "quit.bmp";
+    // --- Helper macro to initialize buttons ---
+#define INIT_BUTTON(ID, LABEL, X, Y, W, H, CLICK, RENDER) \
+    paletteButtons[ID].name = LABEL; \
+    paletteButtons[ID].box.x = (X); \
+    paletteButtons[ID].box.y = (Y); \
+    paletteButtons[ID].box.w = (W); \
+    paletteButtons[ID].box.h = (H); \
+    paletteButtons[ID].OnClick = CLICK; \
+    paletteButtons[ID].render = RENDER;
+
+    #if UNUSED
+        INIT_BUTTON(0, "BrightnessSelector", 775, 10, 16, 64, G_BrightnessButtonOnClick, 0);
+    #endif
+
+    // --- Color Picker ---
+    INIT_BUTTON(1, "ColorPicker", CANVAS_WIDTH + 10, 10, 128, 128, G_ColorPickerOnClick, 0);
+
+    // --- Brush Size Buttons (8 total in two rows) ---
+    {
+        int brushSizes[8] = {1, 2, 3, 4,
+                                   6, 8, 10, 12};
+        char* brushNames[8] = {
+            "BushSize1", "BushSize2", "BushSize3", "BushSize4",
+            "BushSize5", "BushSize6", "BushSize7", "BushSize8"
+        };
+
+        for (int i = 0; i < 8; ++i) {
+            int index = i + 2;
+            int col = i % 4;
+            int row = i / 4;
+            INIT_BUTTON(index,
+                        brushNames[i],
+                        CANVAS_WIDTH + 11 + 32 * col,
+                        195 + row * 32,
+                        30, 30,
+                        G_SetBushSize, 1);
+            paletteButtons[index].data1 = brushSizes[i];
+        }
+    }
+
+    // --- Utility Buttons ---
+    {
+        int utilCount = 5;
+        int indices[]   = {10, 11, 12, 13, 14};
+        char* names[]   = {"SaveButton", "FillButton", "BrushButton", "QuitButton", "Cls"};
+        int offsetX[]   = {0,  32,   0, 32 * 3, 32 * 3};
+        int offsetY[]   = {0, -32, -32,      0,    -32};
path: elkscmd/gui/app.c
user: login: Vutshi
body: Oh, no I was not aware of this. I was just looking for a way to simplify new buttons addition but I couldn’t achieve it with macros only. 
I will rewrite it on next PR
created_at: 2025-04-06T22:07:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -61,132 +59,81 @@ void A_InitPalette(void)
 
 
     // Create and configure buttons
-#if UNUSED
-    paletteButtons[0].name = "BrightnessSelector";
-    paletteButtons[0].box.x = 775;
-    paletteButtons[0].box.y = 10;
-    paletteButtons[0].box.w = 16;
-    paletteButtons[0].box.h = 64;
-    paletteButtons[0].OnClick = G_BrightnessButtonOnClick;
-    paletteButtons[0].render = false;
-#endif
-    paletteButtons[1].name = "ColorPicker";
-    paletteButtons[1].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[1].box.y = 10;
-    paletteButtons[1].box.w = 128;
-    paletteButtons[1].box.h = 128;
-    paletteButtons[1].OnClick = G_ColorPickerOnClick;
-    paletteButtons[1].render = false;
-
-    // Bush Sizes 1
-    paletteButtons[2].name = "BushSize1";
-    paletteButtons[2].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[2].box.y = 195;
-    paletteButtons[2].box.w = 30;
-    paletteButtons[2].box.h = 30;
-    paletteButtons[2].OnClick = G_SetBushSize;
-    paletteButtons[2].data1 = 1;
-    paletteButtons[2].render = true;
-
-    // Bush Sizes 2
-    paletteButtons[3].name = "BushSize2";
-    paletteButtons[3].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[3].box.y = 195;
-    paletteButtons[3].box.w = 30;
-    paletteButtons[3].box.h = 30;
-    paletteButtons[3].OnClick = G_SetBushSize;
-    paletteButtons[3].data1 = 2;
-    paletteButtons[3].render = true;
-
-    // Bush Sizes 3
-    paletteButtons[4].name = "BushSize3";
-    paletteButtons[4].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[4].box.y = 195;
-    paletteButtons[4].box.w = 30;
-    paletteButtons[4].box.h = 30;
-    paletteButtons[4].OnClick = G_SetBushSize;
-    paletteButtons[4].data1 = 3;
-    paletteButtons[4].render = true;
-
-    // Bush Sizes 4
-    paletteButtons[5].name = "BushSize4";
-    paletteButtons[5].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[5].box.y = 195;
-    paletteButtons[5].box.w = 30;
-    paletteButtons[5].box.h = 30;
-    paletteButtons[5].OnClick = G_SetBushSize;
-    paletteButtons[5].data1 = 4;
-    paletteButtons[5].render = true;
-
-    // Bush Sizes 5
-    paletteButtons[6].name = "BushSize5";
-    paletteButtons[6].box.x = SCREEN_WIDTH + 11 + 32*0;
-    paletteButtons[6].box.y = 227;
-    paletteButtons[6].box.w = 30;
-    paletteButtons[6].box.h = 30;
-    paletteButtons[6].OnClick = G_SetBushSize;
-    paletteButtons[6].data1 = 6;
-    paletteButtons[6].render = true;
-
-    // Bush Sizes 6
-    paletteButtons[7].name = "BushSize6";
-    paletteButtons[7].box.x = SCREEN_WIDTH + 11 + 32*1;
-    paletteButtons[7].box.y = 227;
-    paletteButtons[7].box.w = 30;
-    paletteButtons[7].box.h = 30;
-    paletteButtons[7].OnClick = G_SetBushSize;
-    paletteButtons[7].data1 = 8;
-    paletteButtons[7].render = true;
-
-    // Bush Sizes 7
-    paletteButtons[8].name = "BushSize7";
-    paletteButtons[8].box.x = SCREEN_WIDTH + 11 + 32*2;
-    paletteButtons[8].box.y = 227;
-    paletteButtons[8].box.w = 30;
-    paletteButtons[8].box.h = 30;
-    paletteButtons[8].OnClick = G_SetBushSize;
-    paletteButtons[8].data1 = 10;
-    paletteButtons[8].render = true;
-
-    // Bush Sizes 8
-    paletteButtons[9].name = "BushSize8";
-    paletteButtons[9].box.x = SCREEN_WIDTH + 11 + 32*3;
-    paletteButtons[9].box.y = 227;
-    paletteButtons[9].box.w = 30;
-    paletteButtons[9].box.h = 30;
-    paletteButtons[9].OnClick = G_SetBushSize;
-    paletteButtons[9].data1 = 12;
-    paletteButtons[9].render = true;
-
-    // Save
-    paletteButtons[10].name = "SaveButton";
-    paletteButtons[10].box.x = SCREEN_WIDTH + 10;
-    paletteButtons[10].box.y = 300;
-    paletteButtons[10].box.w = 32;
-    paletteButtons[10].box.h = 32;
-    paletteButtons[10].OnClick = G_SaveButtonOnClick;
-    paletteButtons[10].render = true;
-    paletteButtons[10].fileName = LIBPATH "save.bmp";
-
-    // Clear Screen
-    paletteButtons[11].name = "Cls";
-    paletteButtons[11].box.x = SCREEN_WIDTH + 10 + 32*2;
-    paletteButtons[11].box.y = 300;
-    paletteButtons[11].box.w = 32;
-    paletteButtons[11].box.h = 32;
-    paletteButtons[11].OnClick = G_ClearScreen;
-    paletteButtons[11].render = true;
-    paletteButtons[11].fileName = LIBPATH "cls.bmp";
-
-    // Quit
-    paletteButtons[12].name = "QuitButton";
-    paletteButtons[12].box.x = SCREEN_WIDTH + 10 + 32*3;
-    paletteButtons[12].box.y = 300;
-    paletteButtons[12].box.w = 32;
-    paletteButtons[12].box.h = 32;
-    paletteButtons[12].OnClick = G_QuitButtonOnClick;
-    paletteButtons[12].render = true;
-    paletteButtons[12].fileName = LIBPATH "quit.bmp";
+    // --- Helper macro to initialize buttons ---
+#define INIT_BUTTON(ID, LABEL, X, Y, W, H, CLICK, RENDER) \
+    paletteButtons[ID].name = LABEL; \
+    paletteButtons[ID].box.x = (X); \
+    paletteButtons[ID].box.y = (Y); \
+    paletteButtons[ID].box.w = (W); \
+    paletteButtons[ID].box.h = (H); \
+    paletteButtons[ID].OnClick = CLICK; \
+    paletteButtons[ID].render = RENDER;
+
+    #if UNUSED
+        INIT_BUTTON(0, "BrightnessSelector", 775, 10, 16, 64, G_BrightnessButtonOnClick, 0);
+    #endif
+
+    // --- Color Picker ---
+    INIT_BUTTON(1, "ColorPicker", CANVAS_WIDTH + 10, 10, 128, 128, G_ColorPickerOnClick, 0);
+
+    // --- Brush Size Buttons (8 total in two rows) ---
+    {
+        int brushSizes[8] = {1, 2, 3, 4,
+                                   6, 8, 10, 12};
+        char* brushNames[8] = {
+            "BushSize1", "BushSize2", "BushSize3", "BushSize4",
+            "BushSize5", "BushSize6", "BushSize7", "BushSize8"
+        };
+
+        for (int i = 0; i < 8; ++i) {
+            int index = i + 2;
+            int col = i % 4;
+            int row = i / 4;
+            INIT_BUTTON(index,
+                        brushNames[i],
+                        CANVAS_WIDTH + 11 + 32 * col,
+                        195 + row * 32,
+                        30, 30,
+                        G_SetBushSize, 1);
+            paletteButtons[index].data1 = brushSizes[i];
+        }
+    }
+
+    // --- Utility Buttons ---
+    {
+        int utilCount = 5;
+        int indices[]   = {10, 11, 12, 13, 14};
+        char* names[]   = {"SaveButton", "FillButton", "BrushButton", "QuitButton", "Cls"};
+        int offsetX[]   = {0,  32,   0, 32 * 3, 32 * 3};
+        int offsetY[]   = {0, -32, -32,      0,    -32};
path: elkscmd/gui/app.c
user: login: ghaerr
body: I like the new coding and ease of inspection of the initializers for each case, I don't think any rewrite is necessary except just applying static prefix to the declarations of the arrays (only).
created_at: 2025-04-06T22:15:36Z
author_association: OWNER

PR comments:
user: login: ghaerr
created_at: 2025-04-06T21:55:06Z
body: Wow, you're going to town on this! Nice, thank you! :)
author_association: OWNER
user: login: ghaerr
created_at: 2025-04-06T22:13:52Z
body: > add indication of brush/fill either in icons (XOR it?) or in cursor

I still kind of like the idea of a bucket cursor, (and not sure if we need two sizes of it, one would likely do), but I can add XOR drawing if you'd like to play with it. XOR drawing will be handled by the VGA hardware using `set_op(0x18)` before the draw code and then set_op(0) afterwards. There's a version of that macro in drawxcanline.c for ia16.c. I need to know just a little more to know how to best implement it.

Are you thinking of indicating this via XOR drawing of the brush or bucket icon? That might result in funny colors, given that the VGA will do a physical XOR of the actual color number, rather than say, reversing colors. Another idea would be drawing a white line around the icon. I still think the simplest and most obvious for users would be changing the cursor when the fill mode is pending a mouse down.
author_association: OWNER
user: login: Vutshi
created_at: 2025-04-06T22:27:42Z
body: > That might result in funny colors, given that the VGA will do a physical XOR of the actual color number, rather than say, reversing colors.

Yeah, maybe for icons it is not optimal. I was also thinking how to implement a circle (not disk) drawing. I’d like to have circle updating itself on the fly while user changes its radius. The cheapest way is probably using XOR. 
author_association: CONTRIBUTOR
user: login: ghaerr
created_at: 2025-04-06T22:32:42Z
body: I'll put together a test drawpixel_xor() for you to play with for now.
author_association: OWNER