📄 vbindiff.cpp
字号:
for (i = 0; i < numLines; i++) {// cerr << i << '\n'; char* str = buf2; str += sprintf(str, "%04X %04X:",Word(lineOffset>>16),Word(lineOffset&0xFFFF)); lineLength = min(lineWidth, bufContents - i*lineWidth); for (j = 0, index = -1; j < lineLength; j++) { if (j % 8 == 0) { *(str++) = ' '; ++index; } str += sprintf(str, "%02X ", data->line[i][j]); buf[index++] = displayTable[data->line[i][j]]; } memset(buf + index, ' ', sizeof(buf) - index - 1); memset(str, ' ', screenWidth - (str - buf2)); win.put(0,i+1, buf2); win.put(leftMar2,i+1, buf); if (diffs) for (j = 0; j < lineWidth; j++) if (diffs->data->line[i][j]) { win.putAttribs(j*3 + leftMar + (j>7),i+1, cFileDiff,2); win.putAttribs(j + leftMar2 + (j>7),i+1, cFileDiff,1); } lineOffset += lineWidth; } // end for i up to numLines win.update();} // end FileDisplay::display//--------------------------------------------------------------------// Edit the file://// Returns:// true: File changed// false: File did not changebool FileDisplay::edit(const FileDisplay* other){ if (!bufContents && offset) return false; // You must not be completely past EOF if (!writable) { File w = OpenFile(fileName, true); if (w == InvalidFile) return false; CloseFile(file); file = w; writable = true; } if (bufContents < bufSize) memset(data->buffer + bufContents, 0, bufSize - bufContents); short x = 0; short y = 0; bool hiNib = true; bool ascii = false; bool changed = false; int key; const Byte *const inputTable = ((displayTable == ebcdicDisplayTable) ? ascii2ebcdicTable : NULL); // No translation showEditPrompt(); win.setCursor(leftMar,1); ConWindow::showCursor(); for (;;) { win.setCursor((ascii ? leftMar2 + x : leftMar + 3*x + !hiNib) + (x / 8), y+1); key = win.readKey(); switch (key) { case KEY_ESCAPE: goto done; case KEY_TAB: hiNib = true; ascii = !ascii; break; case KEY_DELETE: case KEY_BACKSPACE: case KEY_LEFT: if (!hiNib) hiNib = true; else { if (!ascii) hiNib = false; if (--x < 0) x = lineWidth-1; } if (hiNib || (x < lineWidth-1)) break; // else fall thru case KEY_UP: if (--y < 0) y = numLines-1; break; default: { short newByte = -1; if ((key == KEY_RETURN) && other && (other->bufContents > x + y*lineWidth)) { newByte = other->data->line[y][x]; // Copy from other file hiNib = ascii; // Always advance cursor to next byte } else if (ascii) { if (isprint(key)) newByte = (inputTable ? inputTable[key] : key); } else { // hex if (isdigit(key)) newByte = key - '0'; else if (isxdigit(key)) newByte = safeUC(key) - 'A' + 10; if (newByte >= 0) { if (hiNib) newByte = (newByte * 0x10) | (0x0F & data->line[y][x]); else newByte |= 0xF0 & data->line[y][x]; } // end if valid digit entered } // end else hex if (newByte >= 0) { changed = true; setByte(x,y,newByte); } else break; } // end default and fall thru case KEY_RIGHT: if (hiNib && !ascii) hiNib = false; else { hiNib = true; if (++x >= lineWidth) x = 0; } if (x || !hiNib) break; // else fall thru case KEY_DOWN: if (++y >= numLines) y = 0; break; } // end switch } // end forever done: if (changed) { promptWin.clear(); promptWin.border(); promptWin.put(30,1,"Save changes (Y/N):"); promptWin.update(); promptWin.setCursor(50,1); key = promptWin.readKey(); if (safeUC(key) != 'Y') { changed = false; moveTo(offset); // Re-read buffer contents } else { SeekFile(file, offset); WriteFile(file, data->buffer, bufContents); } } showPrompt(); ConWindow::hideCursor(); return changed;} // end FileDisplay::edit//--------------------------------------------------------------------void FileDisplay::setByte(short x, short y, Byte b){ if (x + y*lineWidth >= bufContents) { if (x + y*lineWidth > bufContents) { short y1 = bufContents / lineWidth; short x1 = bufContents % lineWidth; while (y1 <= numLines) { while (x1 < lineWidth) { if ((x1 == x) && (y1 == y)) goto done; setByte(x1,y1,0); ++x1; } x1 = 0; ++y1; } // end while y1 } // end if more than 1 byte past the end done: ++bufContents; data->line[y][x] = b ^ 1; // Make sure it's different } // end if past the end if (data->line[y][x] != b) { data->line[y][x] = b; char str[3]; sprintf(str, "%02X", b); win.setAttribs(cFileEdit); win.put(leftMar + 3*x + (x / 8), y+1, str); str[0] = displayTable[b]; str[1] = '\0'; win.put(leftMar2 + x + (x / 8), y+1, str); win.setAttribs(cFileWin); win.update(); }} // end FileDisplay::setByte//--------------------------------------------------------------------// Change the file position://// Changes the file offset and updates the buffer.// Does not update the display.//// Input:// step:// The number of bytes to move// A negative value means to move backward//// void FileDisplay::move(int step) /* Inline function *///--------------------------------------------------------------------// Change the file position://// Changes the file offset and updates the buffer.// Does not update the display.//// Input:// newOffset:// The new position of the filevoid FileDisplay::moveTo(FPos newOffset){ if (!fileName[0]) return; // No file offset = newOffset; if (offset < 0) offset = 0; SeekFile(file, offset); bufContents = ReadFile(file, data->buffer, bufSize);} // end FileDisplay::moveTo//--------------------------------------------------------------------// Change the file position by searching://// Changes the file offset and updates the buffer.// Does not update the display.//// Input:// searchFor: The bytes to search for// searchLen: The number of bytes in searchFor//// Returns:// true: The search was successful// false: Search unsuccessful, file not movedbool FileDisplay::moveTo(const Byte* searchFor, int searchLen){ if (!fileName[0]) return true; // No file, pretend success // Using algorithm based on QuickSearch: // http://www-igm.univ-mlv.fr/~lecroq/string/node19.htm // Compute offset table: int i; int moveOver[256]; for (i = 0; i < 256; ++i) moveOver[i] = searchLen + 1; for (i = 0; i < searchLen; ++i) moveOver[searchFor[i]] = searchLen - i; // Prepare the search buffer: const int blockSize = 8 * 1024, moveLength = searchLen, restartAt = blockSize - moveLength, fullStop = blockSize * 2 - moveLength; Byte *const searchBuf = new Byte[2 * blockSize]; Byte *const copyTo = searchBuf + restartAt; const Byte *const copyFrom = searchBuf + fullStop; char *const readAt = reinterpret_cast<char*>(searchBuf) + blockSize; FPos newPos = offset + 1; SeekFile(file, newPos); Size bytesRead = ReadFile(file, searchBuf, blockSize * 2); int stopAt = bytesRead - moveLength; // Start the search: i = 0; for (;;) { if (stopAt < fullStop) ++stopAt; while (i < stopAt) { if (memcmp(searchFor, searchBuf + i, searchLen) == 0) goto done; i += moveOver[searchBuf[i + searchLen]]; // shift } // end while more buffer to search if (stopAt != fullStop) { i = -1; goto done; } // Nothing more to read newPos += blockSize; i -= blockSize; memcpy(copyTo, copyFrom, moveLength); bytesRead = ReadFile(file, readAt, blockSize); stopAt = bytesRead + blockSize - moveLength; } // end forever done: delete [] searchBuf; if (i < 0) return false; // No match moveTo(newPos + i); return true;} // end FileDisplay::moveTo//--------------------------------------------------------------------// Move to the end of the file://// Input:// other: If non NULL, move both files to the end of the shorter filevoid FileDisplay::moveToEnd(FileDisplay* other){ if (!fileName[0]) return; // No file FPos end = SeekFile(file, 0, SeekEnd); FPos diff = 0; if (other) { // If the files aren't currently at the same position, // we want to keep them offset by the same amount: diff = other->offset - offset; end = min(end, SeekFile(other->file, 0, SeekEnd) - diff); } // end if moving other file too end -= steps[cmmMovePage]; end -= end % 0x10; moveTo(end); if (other) other->moveTo(end + diff);} // end FileDisplay::moveToEnd//--------------------------------------------------------------------// Open a file for display://// Opens the file, updates the filename display, and reads the start// of the file into the buffer.//// Input:// aFileName: The name of the file to open//// Returns:// True: Operation successful// False: Unable to open file (call ErrorMsg for error message)bool FileDisplay::setFile(const char* aFileName){ strncpy(fileName, aFileName, maxPath); fileName[maxPath-1] = '\0'; win.put(0,0, fileName); win.putAttribs(0,0, cFileName, screenWidth); win.update(); // FIXME bufContents = 0; file = OpenFile(fileName); writable = false; if (file == InvalidFile) return false; offset = 0; bufContents = ReadFile(file, data->buffer, bufSize); return true;} // end FileDisplay::setFile//====================================================================// Main Program://--------------------------------------------------------------------void calcScreenLayout(bool resize = true){ int screenX, screenY; ConWindow::getScreenSize(screenX, screenY); if (screenX < screenWidth) { ostringstream err; err << "The screen must be at least " << screenWidth << " characters wide."; exitMsg(2, err.str().c_str()); } if (screenY < promptHeight + 4) { ostringstream err; err << "The screen must be at least " << (promptHeight + 4) << " lines high."; exitMsg(2, err.str().c_str()); } numLines = screenY - promptHeight - (singleFile ? 1 : 2); if (singleFile) linesBetween = 0; else { linesBetween = numLines % 2; numLines = (numLines - linesBetween) / 2; } bufSize = numLines * lineWidth; steps[cmmMovePage] = bufSize-lineWidth; // FIXME resize existing windows} // end calcScreenLayout//--------------------------------------------------------------------void displayCharacterSet(){ const bool isASCII = (displayTable == asciiDisplayTable); promptWin.putAttribs(3,2, (isASCII ? cCurrentMode : cBackground), 5); promptWin.putAttribs(9,2, (isASCII ? cBackground : cCurrentMode), 6); promptWin.update();} // end displayCharacterSet//--------------------------------------------------------------------void displayLockState(){#ifndef WIN32_CONSOLE // The Win32 version uses Ctrl & Alt instead if (singleFile) return; promptWin.putAttribs(63,1, ((lockState == lockBottom) ? cCurrentMode : cBackground), 8); promptWin.putAttribs(63,2, ((lockState == lockTop) ? cCurrentMode : cBackground), 11);#endif} // end displayLockState//--------------------------------------------------------------------// Print a message to stderr and exit://// Input:// status: The exit status to use// message: The message to printvoid exitMsg(int status, const char* message){ ConWindow::shutdown(); cerr << endl << message << endl; exit(status);} // end exitMsg//--------------------------------------------------------------------// Normalize the string in the input window://// Does nothing unless splitHex mode is active.//// Input:// pos: The position of the cursor in buf//// Returns:// true: The input buffer was changed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -