void DataView::InvalidateRange(int32 start, int32 end) { if (start <= 0 && end >= int32(fDataSize) - 1) { Invalidate(); return; } int32 startLine = start / kBlockSize; int32 endLine = end / kBlockSize; if (endLine > startLine) { start = startLine * kBlockSize; end = (endLine + 1) * kBlockSize - 1; } // the part with focus BRect rect = SelectionFrame(fFocus, start, end); rect.bottom++; rect.right++; Invalidate(rect); // the part without focus rect = SelectionFrame(fFocus == kHexFocus ? kAsciiFocus : kHexFocus, start, end); rect.bottom++; rect.right++; Invalidate(rect); }
void DataView::InitiateDrag(view_focus focus) { BMessage *drag = new BMessage(B_MIME_DATA); // Add originator and action drag->AddPointer("be:originator", this); //drag->AddString("be:clip_name", "Byte Clipping"); //drag->AddInt32("be_actions", B_TRASH_TARGET); // Add data (just like in Copy()) uint8 *data = fData + fStart; size_t length = fEnd + 1 - fStart; drag->AddData(B_FILE_MIME_TYPE, B_MIME_TYPE, data, length); if (is_valid_utf8(data, length)) drag->AddData("text/plain", B_MIME_TYPE, data, length); // get a frame that contains the whole selection - SelectionFrame() // only spans a rectangle between the start and the end point, so // we have to pass it the correct input values BRect frame; const int32 width = kBlockSize - 1; int32 first = fStart & ~width; int32 last = ((fEnd + width) & ~width) - 1; if (first == (last & ~width)) frame = SelectionFrame(focus, fStart, fEnd); else frame = SelectionFrame(focus, first, last); BRect bounds = Bounds(); if (!bounds.Contains(frame)) frame = bounds & frame; DragMessage(drag, frame, NULL); fStoredStart = fStart; fStoredEnd = fEnd; fDragMessageSize = length; }
void DataView::DrawSelectionBlock(view_focus which, int32 blockStart, int32 blockEnd) { if (fFileSize == 0) return; // draw first line SetDrawingMode(B_OP_INVERT); int32 start = blockStart % kBlockSize; int32 first = (blockStart / kBlockSize) * kBlockSize; int32 end = blockEnd; if (end > first + (int32)kBlockSize - 1) end = first + kBlockSize - 1; FillRect(SelectionFrame(which, first + start, end)); first += kBlockSize; // draw block (and last line) if necessary end = blockEnd % kBlockSize; int32 last = (blockEnd / kBlockSize) * kBlockSize; if (last >= first) { if (end == kBlockSize - 1) last += kBlockSize; if (last > first) FillRect(SelectionFrame(which, first, last - 1)); if (end != kBlockSize - 1) FillRect(SelectionFrame(which, last, last + end)); } SetDrawingMode(B_OP_COPY); }
void DataView::MakeVisible(int32 position) { if (position < 0 || position > int32(fDataSize) - 1) return; BRect frame = SelectionFrame(fFocus, position, position); BRect bounds = Bounds(); if (bounds.Contains(frame)) return; // special case the first and the last line and column, so that // we can take kHorizontalSpace & kVerticalSpace into account if ((position % kBlockSize) == 0) frame.left -= kHorizontalSpace; else if ((position % kBlockSize) == kBlockSize - 1) frame.right += kHorizontalSpace; if (position < int32(kBlockSize)) frame.top -= kVerticalSpace; else if (position > int32(fDataSize - kBlockSize)) frame.bottom += kVerticalSpace; // compute the scroll point BPoint point = bounds.LeftTop(); if (bounds.left > frame.left) point.x = frame.left; else if (bounds.right < frame.right) point.x = frame.right - bounds.Width(); if (bounds.top > frame.top) point.y = frame.top; else if (bounds.bottom < frame.bottom) point.y = frame.bottom - bounds.Height(); ScrollTo(point); }
void DataView::DrawSelectionFrame(view_focus which) { if (fFileSize == 0) return; bool drawBlock = false; bool drawLastLine = false; BRect block, lastLine; int32 spacing = 0; if (which == kAsciiFocus) spacing++; // draw first line int32 start = fStart % kBlockSize; int32 first = (fStart / kBlockSize) * kBlockSize; int32 end = fEnd; if (end > first + (int32)kBlockSize - 1) end = first + kBlockSize - 1; BRect firstLine = SelectionFrame(which, first + start, end); firstLine.right += spacing; first += kBlockSize; // draw block (and last line) if necessary end = fEnd % kBlockSize; int32 last = (fEnd / kBlockSize) * kBlockSize; if (last >= first) { if (end == kBlockSize - 1) last += kBlockSize; if (last > first) { block = SelectionFrame(which, first, last - 1); block.right += spacing; drawBlock = true; } if (end != kBlockSize - 1) { lastLine = SelectionFrame(which, last, last + end); lastLine.right += spacing; drawLastLine = true; } } SetDrawingMode(B_OP_INVERT); BeginLineArray(8); // +******* // | * // +------+ const rgb_color color = {0, 0, 0}; float bottom; if (drawBlock) bottom = block.bottom; else bottom = firstLine.bottom; AddLine(BPoint(firstLine.left + 1, firstLine.top), firstLine.RightTop(), color); AddLine(BPoint(firstLine.right, firstLine.top + 1), BPoint(firstLine.right, bottom), color); // *-------+ // * | // ********* BRect rect; if (start == 0 || (!drawBlock && !drawLastLine)) rect = firstLine; else if (drawBlock) rect = block; else rect = lastLine; if (drawBlock) rect.bottom = block.bottom; if (drawLastLine) { rect.bottom = lastLine.bottom; rect.right = lastLine.right; } rect.bottom++; AddLine(rect.LeftTop(), rect.LeftBottom(), color); AddLine(BPoint(rect.left + 1, rect.bottom), rect.RightBottom(), color); // *--------+ // * | // +**** | // | | if (start && (drawLastLine || drawBlock)) { AddLine(firstLine.LeftTop(), firstLine.LeftBottom(), color); float right = firstLine.left; if (!drawBlock && right > lastLine.right) right = lastLine.right; AddLine(BPoint(rect.left + 1, rect.top), BPoint(right, rect.top), color); } // | | // | ***** // | * // +--------+ if (drawLastLine) { AddLine(lastLine.RightBottom(), BPoint(lastLine.right, lastLine.top + 1), color); if (!drawBlock && lastLine.right <= firstLine.left) lastLine.right = firstLine.left + (lastLine.right < firstLine.left ? 0 : 1); AddLine(BPoint(lastLine.right, lastLine.top), BPoint(firstLine.right, lastLine.top), color); } EndLineArray(); SetDrawingMode(B_OP_COPY); }
void DataView::KeyDown(const char *bytes, int32 numBytes) { int32 modifiers; if (Looper()->CurrentMessage() == NULL || Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK) modifiers = ::modifiers(); // check if the selection is going to be changed switch (bytes[0]) { case B_LEFT_ARROW: case B_RIGHT_ARROW: case B_UP_ARROW: case B_DOWN_ARROW: if (modifiers & B_SHIFT_KEY) { if (fKeySelectionStart == -1) fKeySelectionStart = fStart; } else fKeySelectionStart = -1; break; } switch (bytes[0]) { case B_LEFT_ARROW: { int32 position = fStart - 1; if (modifiers & B_SHIFT_KEY) { if (fKeySelectionStart == fEnd) SetSelection(fStart - 1, fEnd); else { SetSelection(fStart, fEnd - 1); position = fEnd; } } else SetSelection(fStart - 1, fStart - 1); MakeVisible(position); break; } case B_RIGHT_ARROW: { int32 position = fEnd + 1; if (modifiers & B_SHIFT_KEY) { if (fKeySelectionStart == fStart) SetSelection(fStart, fEnd + 1); else SetSelection(fStart + 1, fEnd); } else SetSelection(fEnd + 1, fEnd + 1); MakeVisible(position); break; } case B_UP_ARROW: { int32 start, end; if (modifiers & B_SHIFT_KEY) { if (fKeySelectionStart == fStart) { start = fEnd - int32(kBlockSize); end = fStart; } else { start = fStart - int32(kBlockSize); end = fEnd; } if (start < 0) start = 0; } else { start = fStart - int32(kBlockSize); if (start < 0) start = fStart; end = start; } SetSelection(start, end); MakeVisible(start); break; } case B_DOWN_ARROW: { int32 start, end; if (modifiers & B_SHIFT_KEY) { if (fKeySelectionStart == fEnd) { start = fEnd; end = fStart + int32(kBlockSize); } else { start = fStart; end = fEnd + int32(kBlockSize); } if (end >= int32(fSizeInView)) end = int32(fSizeInView) - 1; } else { end = fEnd + int32(kBlockSize); if (end >= int32(fSizeInView)) start = fEnd; start = end; } SetSelection(start, end); MakeVisible(end); break; } case B_PAGE_UP: { // scroll one page up, but keep the same cursor column BRect frame = SelectionFrame(fFocus, fStart, fStart); frame.OffsetBy(0, -Bounds().Height()); if (frame.top <= kVerticalSpace) frame.top = kVerticalSpace + 1; ScrollBy(0, -Bounds().Height()); int32 position = PositionAt(fFocus, frame.LeftTop()); SetSelection(position, position); break; } case B_PAGE_DOWN: { // scroll one page down, but keep the same cursor column BRect frame = SelectionFrame(fFocus, fStart, fStart); frame.OffsetBy(0, Bounds().Height()); float lastLine = DataBounds().Height() - 1 - kVerticalSpace; if (frame.top > lastLine) frame.top = lastLine; ScrollBy(0, Bounds().Height()); int32 position = PositionAt(fFocus, frame.LeftTop()); SetSelection(position, position); break; } case B_HOME: SetSelection(0, 0); MakeVisible(fStart); break; case B_END: SetSelection(fDataSize - 1, fDataSize - 1); MakeVisible(fStart); break; case B_TAB: SetFocus(fFocus == kHexFocus ? kAsciiFocus : kHexFocus); MakeVisible(fStart); break; case B_FUNCTION_KEY: // this is ignored break; case B_BACKSPACE: if (fBitPosition == 0) SetSelection(fStart - 1, fStart - 1); if (fFocus == kHexFocus) fBitPosition = (fBitPosition + 4) % 8; // supposed to fall through case B_DELETE: SetSelection(fStart, fStart); // to make sure only the cursor is selected if (fFocus == kHexFocus) { const uint8 *data = DataAt(fStart); if (data == NULL) break; uint8 c = data[0] & (fBitPosition == 0 ? 0x0f : 0xf0); // mask out region to be cleared fEditor.Replace(fOffset + fStart, &c, 1); } else fEditor.Replace(fOffset + fStart, (const uint8 *)"", 1); break; default: if (fFocus == kHexFocus) { // only hexadecimal characters are allowed to be entered const uint8 *data = DataAt(fStart); uint8 c = bytes[0]; if (c >= 'A' && c <= 'F') c += 'A' - 'a'; const char *hexNumbers = "0123456789abcdef"; addr_t number; if (data == NULL || (number = (addr_t)strchr(hexNumbers, c)) == 0) break; SetSelection(fStart, fStart); // to make sure only the cursor is selected number -= (addr_t)hexNumbers; fBitPosition = (fBitPosition + 4) % 8; c = (data[0] & (fBitPosition ? 0x0f : 0xf0)) | (number << fBitPosition); // mask out overwritten region and bit-wise or the number to be inserted if (fEditor.Replace(fOffset + fStart, &c, 1) == B_OK && fBitPosition == 0) SetSelection(fStart + 1, fStart + 1); } else { if (fEditor.Replace(fOffset + fStart, (const uint8 *)bytes, numBytes) == B_OK) SetSelection(fStart + 1, fStart + 1); } break; } }
LRESULT CALLBACK SelectionWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: { if (!moving) { HDC hDC = GetDC(hwnd); DefWindowProc(hwnd, message, wParam, lParam); SelectionFrame(hDC, 1, 1, rectSel_dest[2] * zoom / 1000 + 5, rectSel_dest[3] * zoom / 1000 + 5); ReleaseDC(hwnd, hDC); } break; } case WM_LBUTTONDOWN: xPos = LOWORD(lParam); yPos = HIWORD(lParam); SetCapture(hwnd); if (action != 0) SetCursor(LoadCursor(NULL, cursors[action])); moving = TRUE; break; case WM_MOUSEMOVE: if (moving) { TCHAR sizeStr[100]; int xDelta; int yDelta; resetToU1(); xFrac += (short)LOWORD(lParam) - xPos; yFrac += (short)HIWORD(lParam) - yPos; if (zoom < 1000) { xDelta = xFrac * 1000 / zoom; xFrac = 0; yDelta = yFrac * 1000 / zoom; yFrac = 0; } else { xDelta = xFrac * 1000 / zoom; xFrac -= (xFrac * 1000 / zoom) * zoom / 1000; yDelta = yFrac * 1000 / zoom; yFrac -= (yFrac * 1000 / zoom) * zoom / 1000; } switch (action) { case 0: rectSel_dest[0] += xDelta; rectSel_dest[1] += yDelta; break; case 1: rectSel_dest[0] += xDelta; rectSel_dest[1] += yDelta; rectSel_dest[2] -= xDelta; rectSel_dest[3] -= yDelta; break; case 2: rectSel_dest[1] += yDelta; rectSel_dest[3] -= yDelta; break; case 3: rectSel_dest[2] += xDelta; rectSel_dest[1] += yDelta; break; case 4: rectSel_dest[0] += xDelta; rectSel_dest[2] -= xDelta; break; case 5: rectSel_dest[2] += xDelta; break; case 6: rectSel_dest[0] += xDelta; rectSel_dest[2] -= xDelta; rectSel_dest[3] += yDelta; break; case 7: rectSel_dest[3] += yDelta; break; case 8: rectSel_dest[2] += xDelta; rectSel_dest[3] += yDelta; break; } _stprintf(sizeStr, _T("%d x %d"), rectSel_dest[2], rectSel_dest[3]); SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) sizeStr); if (action != 0) StretchBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY); else if (transpBg == 0) MaskBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND)); else { HBITMAP tempMask; HBRUSH oldBrush; HDC tempDC; tempMask = CreateBitmap(rectSel_dest[2], rectSel_dest[3], 1, 1, NULL); oldBrush = SelectObject(hSelDC, CreateSolidBrush(bgColor)); tempDC = CreateCompatibleDC(hSelDC); SelectObject(tempDC, tempMask); MaskBlt(tempDC, 0, 0, rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(NOTSRCCOPY, BLACKNESS)); DeleteDC(tempDC); DeleteObject(SelectObject(hSelDC, oldBrush)); MaskBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, tempMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND)); DeleteObject(tempMask); } SendMessage(hImageArea, WM_PAINT, 0, 0); xPos = LOWORD(lParam); yPos = HIWORD(lParam); //SendMessage(hwnd, WM_PAINT, 0, 0); } else { int w = rectSel_dest[2] * zoom / 1000 + 6; int h = rectSel_dest[3] * zoom / 1000 + 6; xPos = LOWORD(lParam); yPos = HIWORD(lParam); SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) NULL); action = identifyCorner(xPos, yPos, w, h); if (action != 0) SetCursor(LoadCursor(NULL, cursors[action])); } break; case WM_LBUTTONUP: if (moving) { moving = FALSE; ReleaseCapture(); if (action != 0) { HDC hTempDC; HBITMAP hTempBm; hTempDC = CreateCompatibleDC(hSelDC); hTempBm = CreateDIBWithProperties(rectSel_dest[2], rectSel_dest[3]); SelectObject(hTempDC, hTempBm); SelectObject(hSelDC, hSelBm); StretchBlt(hTempDC, 0, 0, rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY); DeleteObject(hSelBm); hSelBm = hTempBm; hTempBm = CreateBitmap(rectSel_dest[2], rectSel_dest[3], 1, 1, NULL); SelectObject(hTempDC, hTempBm); SelectObject(hSelDC, hSelMask); StretchBlt(hTempDC, 0, 0, rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, GetDIBWidth(hSelMask), GetDIBHeight(hSelMask), SRCCOPY); DeleteObject(hSelMask); hSelMask = hTempBm; SelectObject(hSelDC, hSelBm); DeleteDC(hTempDC); } placeSelWin(); ShowWindow(hSelection, SW_HIDE); ShowWindow(hSelection, SW_SHOW); } break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }