@@ -22,7 +22,7 @@ namespace Layout {
2222 static constexpr int MIN_OFFSET_DIGITS = 4 ;
2323 static constexpr int OFFSET_SUFFIX_CHARS = 2 ; // ": "
2424 static constexpr int HEX_CHARS_PER_BYTE = 3 ; // "XX "
25- static constexpr int HEX_MIDDLE_EXTRA_SPACE = 1 ; // Extra space after byte 7
25+ static constexpr int HEX_MIDDLE_EXTRA_SPACE = 1 ; // Extra space after each 8 bytes
2626 static constexpr int HEX_ASCII_SEPARATOR_CHARS = 2 ; // The separator is technically " | ",
2727 // but we get the space on the left by default due to it being included with every byte via HEX_CHARS_PER_BYTE
2828 static constexpr int LEFT_MARGIN_PIXELS = 2 ;
@@ -380,14 +380,38 @@ void CLightningFastViewerWidget::calculateHexLayout()
380380 // Calculate nDigits once and cache it
381381 _nDigits = static_cast <int >(qCeil (::log10 (static_cast <double >(_data.size () + 1 ))));
382382 _nDigits = qMax (Layout::MIN_OFFSET_DIGITS, _nDigits);
383- const int offsetWidth = _charWidth * (_nDigits + Layout::OFFSET_SUFFIX_CHARS) + Layout::LEFT_MARGIN_PIXELS;
384383
385- // Hex area starts after offset
386- _hexStart = offsetWidth;
384+ // Calculate optimal bytesPerLine that fits viewport width (must be multiple of 4)
385+ const int viewportWidth = viewport ()->width ();
386+ int optimalBytesPerLine = 4 ; // Minimum
387+ LineLayout optimalLayout;
387388
388- // ASCII area starts after hex (16 bytes * 3 chars + extra space at middle)
389- const int hexWidth = _charWidth * (_bytesPerLine * Layout::HEX_CHARS_PER_BYTE + Layout::HEX_MIDDLE_EXTRA_SPACE);
390- _asciiStart = _hexStart + hexWidth + _charWidth * Layout::HEX_ASCII_SEPARATOR_CHARS;
389+ // Try increasingly larger values (multiples of 4) until we exceed viewport width
390+ for (int candidate = 4 ; candidate <= 64 ; candidate += 4 )
391+ {
392+ optimalLayout = calculateHexLineLayout (candidate, _nDigits);
393+ const int lineWidth = optimalLayout.asciiStart + optimalLayout.asciiWidth ;
394+ if (lineWidth <= viewportWidth)
395+ optimalBytesPerLine = candidate;
396+ else
397+ break ;
398+ }
399+
400+ _bytesPerLine = optimalBytesPerLine;
401+ _hexStart = optimalLayout.hexStart ;
402+ _asciiStart = optimalLayout.asciiStart ;
403+ }
404+
405+ CLightningFastViewerWidget::LineLayout CLightningFastViewerWidget::calculateHexLineLayout (int bytesPerLine, int nDigits) const
406+ {
407+ LineLayout layout;
408+
409+ layout.hexStart = _charWidth * (nDigits + Layout::OFFSET_SUFFIX_CHARS) + Layout::LEFT_MARGIN_PIXELS;
410+ layout.hexWidth = _charWidth * (bytesPerLine * Layout::HEX_CHARS_PER_BYTE + Layout::HEX_MIDDLE_EXTRA_SPACE * ((bytesPerLine - 1 ) / 8 ));
411+ layout.asciiStart = layout.hexStart + layout.hexWidth + _charWidth * Layout::HEX_ASCII_SEPARATOR_CHARS;
412+ layout.asciiWidth = _charWidth * (bytesPerLine + Layout::HEX_ASCII_SEPARATOR_CHARS);
413+
414+ return layout;
391415}
392416
393417void CLightningFastViewerWidget::calculateTextLayout ()
@@ -440,7 +464,7 @@ void CLightningFastViewerWidget::drawHexLine(QPainter& painter, qsizetype offset
440464 painter.drawText (x - hScroll, y + fm.ascent (), hexByte);
441465 x += _charWidth * Layout::HEX_CHARS_PER_BYTE;
442466
443- if (i == 7 )
467+ if ((i % 8 ) == 7 )
444468 {
445469 x += _charWidth * Layout::HEX_MIDDLE_EXTRA_SPACE;
446470 }
@@ -567,12 +591,14 @@ CLightningFastViewerWidget::Region CLightningFastViewerWidget::regionAtPos(const
567591
568592qsizetype CLightningFastViewerWidget::hexPosToOffset (const QPoint& pos) const
569593{
570- if (_data.isEmpty ()) return -1 ;
594+ if (_data.isEmpty ())
595+ return -1 ;
571596
572- int line = (pos.y () / _lineHeight) + verticalScrollBar ()->value ();
573- if (line < 0 || line >= totalLines ()) return -1 ;
597+ const int line = (pos.y () / _lineHeight) + verticalScrollBar ()->value ();
598+ if (line < 0 || line >= totalLines ())
599+ return -1 ;
574600
575- int x = pos.x () + horizontalScrollBar ()->value ();
601+ const int x = pos.x () + horizontalScrollBar ()->value ();
576602 Region region = regionAtPos (pos);
577603
578604 qsizetype lineOffset = line * _bytesPerLine;
@@ -583,10 +609,10 @@ qsizetype CLightningFastViewerWidget::hexPosToOffset(const QPoint& pos) const
583609 int relX = x - _hexStart;
584610 byteInLine = relX / (_charWidth * Layout::HEX_CHARS_PER_BYTE);
585611
586- // Account for extra space at position 8
587- if (byteInLine >= 8 )
612+ // Account for extra space every 8 bytes
613+ if (byteInLine > 8 )
588614 {
589- relX -= _charWidth * Layout::HEX_MIDDLE_EXTRA_SPACE;
615+ relX -= _charWidth * Layout::HEX_MIDDLE_EXTRA_SPACE * ((byteInLine - 1 ) / 8 ) ;
590616 byteInLine = relX / (_charWidth * Layout::HEX_CHARS_PER_BYTE);
591617 }
592618
@@ -920,4 +946,4 @@ void CLightningFastViewerWidget::updateCursorShape(const QPoint& pos)
920946 }
921947
922948 viewport ()->setCursor (overText ? Qt::IBeamCursor : Qt::ArrowCursor);
923- }
949+ }
0 commit comments