From bd64ea015c09dad60d3bd55fc4575ef8455f415d Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Mon, 19 Jan 2026 15:02:54 -0800 Subject: [PATCH] Allow lowercase letters for array tool pin numbering The ARRAY_AXIS class now accepts lowercase letters (a-z) as input for alphabetic numbering schemes and preserves that case in the output. This allows users to create pin numbers like a1, b1, c1 which are commonly used in DIN 41612 and other backplane connectors. Fixes https://gitlab.com/kicad/code/kicad/-/issues/22787 (cherry picked from commit 56b83095254664c620d52dfef6525dc9597e092a) --- common/array_axis.cpp | 35 +++++++++++++++-- include/array_axis.h | 3 ++ qa/tests/common/test_array_axis.cpp | 59 +++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/common/array_axis.cpp b/common/array_axis.cpp index 9fcb26d52d..e27ad0130b 100644 --- a/common/array_axis.cpp +++ b/common/array_axis.cpp @@ -37,7 +37,11 @@ static bool schemeNonUnitColsStartAt0( ARRAY_AXIS::NUMBERING_TYPE type ) } -ARRAY_AXIS::ARRAY_AXIS() : m_type( NUMBERING_TYPE::NUMBERING_NUMERIC ), m_offset( 0 ), m_step( 1 ) +ARRAY_AXIS::ARRAY_AXIS() : + m_type( NUMBERING_TYPE::NUMBERING_NUMERIC ), + m_offset( 0 ), + m_step( 1 ), + m_useLowercase( false ) { } @@ -76,7 +80,14 @@ std::optional ARRAY_AXIS::getNumberingOffset( const wxString& str ) const for( unsigned i = 0; i < str.length(); i++ ) { - int chIndex = alphabet.Find( str[i], false ); + wxUniChar ch = str[i]; + + // For alphabetic types, convert to uppercase for lookup since our alphabets + // are defined with uppercase letters. This allows users to enter lowercase. + if( !TypeIsNumeric( m_type ) && ch >= 'a' && ch <= 'z' ) + ch = ch - 'a' + 'A'; + + int chIndex = alphabet.Find( ch, false ); if( chIndex == wxNOT_FOUND ) return std::optional{}; @@ -109,6 +120,18 @@ bool ARRAY_AXIS::SetOffset( const wxString& aOffsetName ) if( !offset ) return false; + // For alphabetic types, check if the user entered lowercase letters. + // If so, we'll output lowercase letters as well. + if( !TypeIsNumeric( m_type ) && !aOffsetName.IsEmpty() ) + { + wxUniChar firstChar = aOffsetName[0]; + m_useLowercase = ( firstChar >= 'a' && firstChar <= 'z' ); + } + else + { + m_useLowercase = false; + } + SetOffset( *offset ); return true; } @@ -140,5 +163,11 @@ wxString ARRAY_AXIS::GetItemNumber( int n ) const n = m_offset + m_step * n; - return AlphabeticFromIndex( n, alphabet, nonUnitColsStartAt0 ); + wxString result = AlphabeticFromIndex( n, alphabet, nonUnitColsStartAt0 ); + + // If the user entered a lowercase starting value, output lowercase letters + if( m_useLowercase ) + result = result.Lower(); + + return result; } \ No newline at end of file diff --git a/include/array_axis.h b/include/array_axis.h index 8bd7fafcb7..591129e729 100644 --- a/include/array_axis.h +++ b/include/array_axis.h @@ -125,6 +125,9 @@ private: /// Skip every 'n' numbers. int m_step; + + /// Output lowercase letters when true (for alphabetic types). + bool m_useLowercase; }; #endif // ARRAY_AXIS__H diff --git a/qa/tests/common/test_array_axis.cpp b/qa/tests/common/test_array_axis.cpp index 6236e505bc..7ddfbbad6f 100644 --- a/qa/tests/common/test_array_axis.cpp +++ b/qa/tests/common/test_array_axis.cpp @@ -105,6 +105,32 @@ BOOST_AUTO_TEST_CASE( ValidOffsets ) false, 0, }, + // Lowercase alphabetical input should be accepted and map to same offset as uppercase + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_ALPHA_FULL, + "a", + true, + 0, + }, + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_ALPHA_FULL, + "xy", + true, + 648, + }, + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_ALPHA_NO_IOSQXZ, + "a", + true, + 0, + }, + // Hex lowercase should NOT be accepted (hex only allows uppercase A-F) + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_HEX, + "a0", + false, + 0, + }, }; // clang-format on @@ -187,6 +213,39 @@ static const std::vector axis_name_cases = { 6, { "11", "13", "15", "17", "19", "21" }, }, + { + // Test lowercase alphabetical input produces lowercase output + "Alpha lowercase", + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_ALPHA_FULL, + "a", + 1, + }, + 3, + { "a", "b", "c" }, + }, + { + // Test lowercase alphabetical with 2nd col + "Alpha lowercase 2nd col", + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_ALPHA_FULL, + "y", + 1, + }, + 4, + { "y", "z", "aa", "ab" }, + }, + { + // Test lowercase no-IOSQXZ alphabet + "Alpha no IOSQXZ lowercase", + { + ARRAY_AXIS::NUMBERING_TYPE::NUMBERING_ALPHA_NO_IOSQXZ, + "a", + 1, + }, + 5, + { "a", "b", "c", "d", "e" }, + }, }; // clang-format on