From 33a8cd942f156d7dfcd3d8beedca7f5b58edc740 Mon Sep 17 00:00:00 2001
From: Brendan Hickey <brendan@bhickey.net>
Date: Thu, 20 Mar 2025 11:26:37 +0100
Subject: [PATCH] Increase GerbView max DCode Id to 2^31-1

I (charrasjp) fixed the compil issues of the Brendan Hickey's initial work and some other minor issues.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20323
---
 gerbview/dcode.h                            | 19 +++++++--
 gerbview/excellon_read_drill_file.cpp       |  4 +-
 gerbview/gerber_file_image.cpp              | 45 ++++++++++-----------
 gerbview/gerber_file_image.h                |  4 +-
 gerbview/rs274d.cpp                         |  6 ---
 gerbview/toolbars_gerber.cpp                | 11 ++---
 gerbview/tools/gerbview_inspection_tool.cpp | 12 +++---
 7 files changed, 49 insertions(+), 52 deletions(-)

diff --git a/gerbview/dcode.h b/gerbview/dcode.h
index e7f75d882d..fefc4fbf7a 100644
--- a/gerbview/dcode.h
+++ b/gerbview/dcode.h
@@ -64,11 +64,11 @@ enum APERTURE_DEF_HOLETYPE {
 };
 
 /* define min and max values for D Codes values.
- * note: values >= 0 and < FIRST_DCODE can be used for special purposes
+ * note: values >= 0 and < FIRST_DCODE can be used for special purposes (plot commands)
+ * Revision I1 permits apertures up to 2^31-1.
  */
 #define FIRST_DCODE     10
-#define LAST_DCODE      10000
-#define TOOLS_MAX_COUNT (LAST_DCODE + 1)
+#define LAST_DCODE      0x7FFFFFFF
 
 class APERTURE_MACRO;
 
@@ -81,6 +81,17 @@ class D_CODE
 public:
     D_CODE( int num_dcode );
     ~D_CODE();
+
+    /**
+     * @return true if aDcodeValue is valid ( >= FIRST_DCODE. )
+     * Any value > 0x7FFFFFFF is a negative value for a int and is not acceptable
+     * and is < FIRST_DCODE.
+     */
+    static bool IsValidDcodeValue( int aDcodeValue )
+    {
+        return aDcodeValue >= FIRST_DCODE;
+    }
+
     void Clear_D_CODE_Data();
 
     /**
@@ -187,7 +198,7 @@ public:
     int GetShapeDim( GERBER_DRAW_ITEM* aParent );
 
 public:
-    VECTOR2I                m_Size;         ///< Horizontal and vertical dimensions.
+    VECTOR2I              m_Size;           ///< Horizontal and vertical dimensions.
     APERTURE_T            m_ApertType;      ///< Aperture type ( Line, rectangle, circle,
                                             ///< oval poly, macro )
     int                   m_Num_Dcode;      ///< D code value ( >= 10 )
diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp
index 7a83b98b84..033daa2186 100644
--- a/gerbview/excellon_read_drill_file.cpp
+++ b/gerbview/excellon_read_drill_file.cpp
@@ -921,8 +921,8 @@ bool EXCELLON_IMAGE::Select_Tool( char*& text )
     {
         int dcode_id = tool_id + FIRST_DCODE;     // Remember: dcodes are >= FIRST_DCODE
 
-        if( dcode_id > (TOOLS_MAX_COUNT - 1) )
-            dcode_id = TOOLS_MAX_COUNT - 1;
+        if( !D_CODE::IsValidDcodeValue(dcode_id ) )
+            dcode_id = LAST_DCODE;
 
         m_Current_Tool = dcode_id;
         D_CODE* currDcode = GetDCODE( dcode_id );
diff --git a/gerbview/gerber_file_image.cpp b/gerbview/gerber_file_image.cpp
index a5e6b1be0d..ddc5b8f122 100644
--- a/gerbview/gerber_file_image.cpp
+++ b/gerbview/gerber_file_image.cpp
@@ -29,6 +29,7 @@
 #include <X2_gerber_attributes.h>
 #include <algorithm>
 #include <map>
+//#include <numeric>
 #include <core/arraydim.h>
 #include <core/profile.h>
 
@@ -91,8 +92,7 @@ GERBER_FILE_IMAGE::GERBER_FILE_IMAGE( int aLayer ) :
 
     ResetDefaultValues();
 
-    for( unsigned ii = 0; ii < arrayDim( m_Aperture_List ); ii++ )
-        m_Aperture_List[ii] = nullptr;
+    m_ApertureList.clear();
 }
 
 
@@ -105,8 +105,8 @@ GERBER_FILE_IMAGE::~GERBER_FILE_IMAGE()
 
     m_drawings.clear();
 
-    for( unsigned ii = 0; ii < arrayDim( m_Aperture_List ); ii++ )
-        delete m_Aperture_List[ii];
+    for( const auto& ap_item : m_ApertureList )
+        delete ap_item.second;
 
     delete m_FileFunction;
 }
@@ -127,18 +127,17 @@ void GERBER_FILE_IMAGE::SetDrawOffetAndRotation( VECTOR2D aOffsetMM, EDA_ANGLE a
 
 D_CODE* GERBER_FILE_IMAGE::GetDCODEOrCreate( int aDCODE, bool aCreateIfNoExist )
 {
-    unsigned ndx = aDCODE - FIRST_DCODE;
+    auto it = m_ApertureList.find(aDCODE);
 
-    if( ndx < (unsigned) arrayDim( m_Aperture_List ) )
+    if( it != m_ApertureList.end() )
+        return it->second;
+
+    // lazily create the D_CODE if it does not exist.
+    if( aCreateIfNoExist )
     {
-        // lazily create the D_CODE if it does not exist.
-        if( aCreateIfNoExist )
-        {
-            if( m_Aperture_List[ndx] == nullptr )
-                m_Aperture_List[ndx] = new D_CODE( ndx + FIRST_DCODE );
-        }
-
-        return m_Aperture_List[ndx];
+        D_CODE* dcode = new D_CODE(aDCODE);
+        m_ApertureList.insert({ aDCODE, dcode });
+        return dcode;
     }
 
     return nullptr;
@@ -147,10 +146,10 @@ D_CODE* GERBER_FILE_IMAGE::GetDCODEOrCreate( int aDCODE, bool aCreateIfNoExist )
 
 D_CODE* GERBER_FILE_IMAGE::GetDCODE( int aDCODE ) const
 {
-    unsigned ndx = aDCODE - FIRST_DCODE;
+    auto it = m_ApertureList.find(aDCODE);
 
-    if( ndx < (unsigned) arrayDim( m_Aperture_List ) )
-        return m_Aperture_List[ndx];
+    if ( it != m_ApertureList.end() )
+        return it->second;
 
     return nullptr;
 }
@@ -271,14 +270,14 @@ int GERBER_FILE_IMAGE::GetDcodesCount()
 {
     int count = 0;
 
-    for( unsigned ii = 0; ii < arrayDim( m_Aperture_List ); ii++ )
+    for( const auto& n : m_ApertureList )
     {
-        if( m_Aperture_List[ii] )
-        {
-            if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined )
-                ++count;
-        }
+        D_CODE* dcode = n.second;
 
+        wxCHECK2( dcode, continue );
+
+        if( dcode->m_InUse || dcode->m_Defined )
+            count++;
     }
 
     return count;
diff --git a/gerbview/gerber_file_image.h b/gerbview/gerber_file_image.h
index 3e87fbdfe1..b130fa34aa 100644
--- a/gerbview/gerber_file_image.h
+++ b/gerbview/gerber_file_image.h
@@ -463,8 +463,8 @@ public:
     std::map<wxString, int> m_ComponentsList;            // list of components
     std::map<wxString, int> m_NetnamesList;              // list of net names
 
-    ///< Dcode (Aperture) List for this layer (max TOOLS_MAX_COUNT: see dcode.h)
-    D_CODE*             m_Aperture_List[TOOLS_MAX_COUNT];
+    /// Dcode (Aperture) List for this layer (see dcode.h)
+    std::map<int, D_CODE*> m_ApertureList;
 
     ///< Whether an aperture macro tool is flashed on or off.
     bool               m_Exposure;
diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp
index ad24bbf947..a94a124973 100644
--- a/gerbview/rs274d.cpp
+++ b/gerbview/rs274d.cpp
@@ -479,9 +479,6 @@ bool GERBER_FILE_IMAGE::Execute_G_Command( char*& text, int G_command )
         if( D_commande < FIRST_DCODE )
             return false;
 
-        if( D_commande > (TOOLS_MAX_COUNT - 1) )
-            D_commande = TOOLS_MAX_COUNT - 1;
-
         m_Current_Tool = D_commande;
         D_CODE* pt_Dcode = GetDCODE( D_commande );
 
@@ -570,9 +567,6 @@ bool GERBER_FILE_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
 
     if( D_commande >= FIRST_DCODE )  // This is a "Set tool" command
     {
-        if( D_commande > (TOOLS_MAX_COUNT - 1) )
-            D_commande = TOOLS_MAX_COUNT - 1;
-
         // remember which tool is selected, nothing is done with it in this
         // call
         m_Current_Tool = D_commande;
diff --git a/gerbview/toolbars_gerber.cpp b/gerbview/toolbars_gerber.cpp
index d5a12f248b..50e2fe42dd 100644
--- a/gerbview/toolbars_gerber.cpp
+++ b/gerbview/toolbars_gerber.cpp
@@ -327,12 +327,9 @@ void GERBVIEW_FRAME::updateDCodeSelectBox()
         wxASSERT_MSG( false, wxT( "Invalid units" ) );
     }
 
-    for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ )
+    for( const auto [_, dcode] : gerber->m_ApertureList )
     {
-        D_CODE* dcode = gerber->GetDCODE( ii + FIRST_DCODE );
-
-        if( dcode == nullptr )
-            continue;
+        wxCHECK2( dcode,continue );
 
         if( !dcode->m_InUse && !dcode->m_Defined )
             continue;
@@ -434,10 +431,8 @@ void GERBVIEW_FRAME::updateAperAttributesSelectBox()
         if( gerber->GetDcodesCount() == 0 )
             continue;
 
-        for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ )
+        for( const auto &[_, aperture] : gerber->m_ApertureList )
         {
-            D_CODE* aperture = gerber->GetDCODE( ii + FIRST_DCODE );
-
             if( aperture == nullptr )
                 continue;
 
diff --git a/gerbview/tools/gerbview_inspection_tool.cpp b/gerbview/tools/gerbview_inspection_tool.cpp
index 7f5d41a52b..26fab957db 100644
--- a/gerbview/tools/gerbview_inspection_tool.cpp
+++ b/gerbview/tools/gerbview_inspection_tool.cpp
@@ -68,7 +68,6 @@ void GERBVIEW_INSPECTION_TOOL::Reset( RESET_REASON aReason )
 
 int GERBVIEW_INSPECTION_TOOL::ShowDCodes( const TOOL_EVENT& aEvent )
 {
-    int             ii, jj;
     wxString        Line;
     wxArrayString   list;
     int             curr_layer = m_frame->GetActiveLayer();
@@ -114,18 +113,17 @@ int GERBVIEW_INSPECTION_TOOL::ShowDCodes( const TOOL_EVENT& aEvent )
 
         list.Add( Line );
 
-        for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ )
+        int ii = 1;
+        for( const auto &[_, pt_D_code] : gerber->m_ApertureList )
         {
-            D_CODE* pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE );
-
             if( pt_D_code == nullptr )
                 continue;
 
             if( !pt_D_code->m_InUse && !pt_D_code->m_Defined )
                 continue;
 
-            Line.Printf( wxT( "tool %2.2d:   D%2.2d   V %.4f %s  H %.4f %s   %s  attribute '%s'" ),
-                         jj,
+            Line.Printf( wxT( "tool %d:   Dcode D%d   V %.4f %s  H %.4f %s   %s  attribute '%s'" ),
+                         ii,
                          pt_D_code->m_Num_Dcode,
                          pt_D_code->m_Size.y / scale, units,
                          pt_D_code->m_Size.x / scale, units,
@@ -140,7 +138,7 @@ int GERBVIEW_INSPECTION_TOOL::ShowDCodes( const TOOL_EVENT& aEvent )
                 Line += wxT( " (in use)" );
 
             list.Add( Line );
-            jj++;
+            ii++;
         }
     }