6 """ |
6 """ |
7 Module implementing an editor for binary data. |
7 Module implementing an editor for binary data. |
8 """ |
8 """ |
9 |
9 |
10 from __future__ import unicode_literals |
10 from __future__ import unicode_literals |
11 |
11 try: |
12 import sys |
12 chr = unichr # __IGNORE_EXCEPTION__ |
13 is_Py2 = sys.version_info[0] == 2 |
13 except NameError: |
14 # TODO: use unichr for Python2 |
14 pass |
15 |
15 |
16 from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QByteArray, QTimer, QRect, \ |
16 from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QByteArray, QTimer, QRect, \ |
17 QBuffer, QIODevice |
17 QBuffer, QIODevice |
18 from PyQt5.QtGui import QBrush, QPen, QColor, QFont, QPalette, QKeySequence, \ |
18 from PyQt5.QtGui import QBrush, QPen, QColor, QFont, QPalette, QKeySequence, \ |
19 QPainter |
19 QPainter |
358 self.__pxCharHeight) |
358 self.__pxCharHeight) |
359 x = (pos % (2 * self.BYTES_PER_LINE)) |
359 x = (pos % (2 * self.BYTES_PER_LINE)) |
360 self.__pxCursorX = ( |
360 self.__pxCursorX = ( |
361 (((x // 2) * 3) + (x % 2)) * self.__pxCharWidth + self.__pxPosHexX) |
361 (((x // 2) * 3) + (x % 2)) * self.__pxCharWidth + self.__pxPosHexX) |
362 |
362 |
|
363 self.__setHexCursorRect() |
|
364 |
|
365 # step 4: calculate position of ASCII cursor |
|
366 x = self.__bPosCurrent % self.BYTES_PER_LINE |
|
367 self.__cursorRectAscii = QRect( |
|
368 self.__pxPosAsciiX + x * self.__pxCharWidth - 1, |
|
369 self.__pxCursorY - self.__pxCharHeight + 4, |
|
370 self.__pxCharWidth + 1, self.__pxCharHeight + 1) |
|
371 |
|
372 # step 5: draw new cursors |
|
373 self.__blink = True |
|
374 self.viewport().update(self.__cursorRect) |
|
375 if self.__asciiArea: |
|
376 self.viewport().update(self.__cursorRectAscii) |
|
377 self.currentAddressChanged.emit(self.__bPosCurrent) |
|
378 |
|
379 def __setHexCursorRect(self): |
|
380 """ |
|
381 Private method to set the cursor. |
|
382 """ |
363 if self.__overwriteMode: |
383 if self.__overwriteMode: |
364 self.__cursorRect = QRect( |
384 self.__cursorRect = QRect( |
365 self.__pxCursorX, self.__pxCursorY + self.__pxCursorWidth, |
385 self.__pxCursorX, self.__pxCursorY + self.__pxCursorWidth, |
366 self.__pxCharWidth, self.__pxCursorWidth) |
386 self.__pxCharWidth, self.__pxCursorWidth) |
367 else: |
387 else: |
368 self.__cursorRect = QRect( |
388 self.__cursorRect = QRect( |
369 self.__pxCursorX, self.__pxCursorY - self.__pxCharHeight + 4, |
389 self.__pxCursorX, self.__pxCursorY - self.__pxCharHeight + 4, |
370 self.__pxCursorWidth, self.__pxCharHeight) |
390 self.__pxCursorWidth, self.__pxCharHeight) |
371 |
|
372 # step 4: calculate position of ASCII cursor |
|
373 x = self.__bPosCurrent % self.BYTES_PER_LINE |
|
374 self.__cursorRectAscii = QRect( |
|
375 self.__pxPosAsciiX + x * self.__pxCharWidth - 1, |
|
376 self.__pxCursorY - self.__pxCharHeight + 4, |
|
377 self.__pxCharWidth + 1, self.__pxCharHeight + 1) |
|
378 |
|
379 # step 5: draw new cursors |
|
380 self.__blink = True |
|
381 self.viewport().update(self.__cursorRect) |
|
382 if self.__asciiArea: |
|
383 self.viewport().update(self.__cursorRectAscii) |
|
384 self.currentAddressChanged.emit(self.__bPosCurrent) |
|
385 |
391 |
386 def cursorBytePosition(self): |
392 def cursorBytePosition(self): |
387 """ |
393 """ |
388 Public method to get the cursor position in bytes. |
394 Public method to get the cursor position in bytes. |
389 |
395 |
535 @param on flag indicating the new overwrite mode |
541 @param on flag indicating the new overwrite mode |
536 @type bool |
542 @type bool |
537 """ |
543 """ |
538 self.__overwriteMode = on |
544 self.__overwriteMode = on |
539 self.overwriteModeChanged.emit(self.__overwriteMode) |
545 self.overwriteModeChanged.emit(self.__overwriteMode) |
|
546 |
|
547 # step 1: delete old cursor |
|
548 self.__blink = False |
|
549 self.viewport().update(self.__cursorRect) |
|
550 # step 2: change the cursor rectangle |
|
551 self.__setHexCursorRect() |
|
552 # step 3: draw new cursors |
|
553 self.__blink = True |
|
554 self.viewport().update(self.__cursorRect) |
540 |
555 |
541 def selectionColors(self): |
556 def selectionColors(self): |
542 """ |
557 """ |
543 Public method to get the selection colors. |
558 Public method to get the selection colors. |
544 |
559 |
1472 pxPosX += 3 * self.__pxCharWidth |
1487 pxPosX += 3 * self.__pxCharWidth |
1473 |
1488 |
1474 # render ascii value |
1489 # render ascii value |
1475 if self.__asciiArea: |
1490 if self.__asciiArea: |
1476 by = self.__dataShown[bPosLine + colIdx] |
1491 by = self.__dataShown[bPosLine + colIdx] |
1477 if is_Py2 and (by < 0x20 or by > 0x7e): |
1492 if by < 0x20 or (by > 0x7e and by < 0xa0): |
1478 ch = "." |
|
1479 elif not is_Py2 and \ |
|
1480 (by < 0x20 or (by > 0x7e and by < 0xa0)): |
|
1481 ch = "." |
1493 ch = "." |
1482 else: |
1494 else: |
1483 ch = chr(by) |
1495 ch = chr(by) |
1484 r.setRect( |
1496 r.setRect( |
1485 pxPosAsciiX2, |
1497 pxPosAsciiX2, |
1672 ascStr = "" |
1684 ascStr = "" |
1673 for j in range(16): |
1685 for j in range(16): |
1674 if (i + j) < len(byteArray): |
1686 if (i + j) < len(byteArray): |
1675 hexStr += " {0:02x}".format(byteArray[i + j]) |
1687 hexStr += " {0:02x}".format(byteArray[i + j]) |
1676 by = byteArray[i + j] |
1688 by = byteArray[i + j] |
1677 if is_Py2 and (by < 0x20 or by > 0x7e): |
1689 if by < 0x20 or (by > 0x7e and by < 0xa0): |
1678 ch = "." |
|
1679 elif not is_Py2 and \ |
|
1680 (by < 0x20 or (by > 0x7e and by < 0xa0)): |
|
1681 ch = "." |
1690 ch = "." |
1682 else: |
1691 else: |
1683 ch = chr(by) |
1692 ch = chr(by) |
1684 ascStr += ch |
1693 ascStr += ch |
1685 result += "{0} {1:<48} {2:<17}\n".format(addrStr, hexStr, ascStr) |
1694 result += "{0} {1:<48} {2:<17}\n".format(addrStr, hexStr, ascStr) |