📄 vbindiff.cpp
字号:
// false: No changes were necessarybool InputManager::normalize(int pos){ if (!splitHex) return false; // Change D_ to 0D: if (pos && buf[pos] == ' ' && buf[pos-1] != ' ') { buf[pos] = buf[pos-1]; buf[pos-1] = '0'; if (pos == len) len += 2; return true; } // Change _D to 0D: if (pos < len && buf[pos] == ' ' && buf[pos+1] != ' ') { buf[pos] = '0'; return true; } return false; // No changes necessary} // end InputManager::normalize//--------------------------------------------------------------------// Get a string using inWin://// Input:// buf: The buffer where the string will be stored// maxLen: The maximum number of chars to accept (not including NUL byte)// history: The history vector to use// restrict: If not NULL, accept only chars in this string// upcase: If true, convert all chars with safeUCvoid getString(char* buf, int maxLen, StrVec& history, const char* restrict=NULL, bool upcase=false, bool splitHex=false){ InputManager manager(buf, maxLen, history); manager.setCharacters(restrict); manager.setSplitHex(splitHex); manager.setUpcase(upcase); manager.run();} // end getString//--------------------------------------------------------------------// Construct the InputManager object://// Input:// aBuf: The buffer where the string will be stored// aMaxLen: The maximum number of chars to accept (not including NUL byte)// aHistory: The history vector to useInputManager::InputManager(char* aBuf, int aMaxLen, StrVec& aHistory): buf(aBuf), restrict(NULL), history(aHistory), historyPos(aHistory.size()), maxLen(aMaxLen), len(0), i(0), upcase(false), splitHex(false), insert(true){} // end InputManager//--------------------------------------------------------------------// Run the main loop to get an input string://// Returns:// true: Enter was pressed// false: Escape was pressedbool InputManager::run(){ inWin.setCursor(2,1); bool inWinShown = false; bool done = false; bool aborted = true; ConWindow::showCursor(insert); memset(buf, ' ', maxLen); buf[maxLen] = '\0'; // We need to be able to display complete bytes: if (splitHex && (maxLen % 3 == 1)) --maxLen; // Main input loop: while (!done) { inWin.put(2,1,buf); if (inWinShown) inWin.update(1); // Only update inside the box else { inWin.update(); inWinShown = true; } // Show the input window inWin.setCursor(2+i,1); int key = inWin.readKey(); if (upcase) key = safeUC(key); switch (key) { case KEY_ESCAPE: buf[0] = '\0'; done = true; break; // ESC case KEY_RETURN: // Enter normalize(i); buf[len] = '\0'; done = true; aborted = false; break; case KEY_BACKSPACE: case KEY_DELETE: // Backspace on most Unix terminals case 0x08: // Backspace (Ctrl-H) if (!i) continue; // Can't back up if we're at the beginning already if (splitHex) { if ((i % 3) == 0) { // At the beginning of a byte; erase last digit of previous byte: if (i == len) len -= 2; i -= 2; buf[i] = ' '; } else if (i < len && buf[i] != ' ') { // On the second digit; erase the first digit: buf[--i] = ' '; } else { // On a blank second digit; delete the entire byte: buf[--i] = ' '; memmove(buf + i, buf + i + 3, maxLen - i - 3); len -= 3; if (len < i) len = i; } } else { // not splitHex mode memmove(buf + i - 1, buf + i, maxLen - i); buf[maxLen-1] = ' '; --len; --i; } // end else not splitHex mode break; case 0x04: // Ctrl-D case KEY_DC: if (i >= len) continue; if (splitHex) { i -= i%3; memmove(buf + i, buf + i + 3, maxLen - i - 3); len -= 3; if (len < i) len = i; } else { memmove(buf + i, buf + i + 1, maxLen - i - 1); buf[maxLen-1] = ' '; --len; } // end else not splitHex mode break; case KEY_IC: insert = !insert; ConWindow::showCursor(insert); break; case 0x02: // Ctrl-B case KEY_LEFT: if (i) { --i; if (splitHex) { normalize(i+1); if (i % 3 == 2) --i; } } break; case 0x06: // Ctrl-F case KEY_RIGHT: if (i < len) { ++i; if (splitHex) { normalize(i-1); if ((i < maxLen) && (i % 3 == 2)) ++i; } } break; case 0x0B: // Ctrl-K if (len > i) { memset(buf + i, ' ', len - i); len = i; } break; case 0x01: // Ctrl-A case KEY_HOME: normalize(i); i = 0; break; case 0x05: // Ctrl-E case KEY_END: if (splitHex && (i < len)) normalize(i); i = len; break; case 0x10: // Ctrl-P case KEY_UP: if (historyPos == 0) beep(); else useHistory(-1); break; case 0x0E: // Ctrl-N case KEY_DOWN: if (historyPos == history.size()) beep(); else useHistory(+1); break; default: if (isprint(key) && (!restrict || strchr(restrict, key))) { if (insert) { if (splitHex) { if (buf[i] == ' ') { if (i >= maxLen) continue; } else { if (len >= maxLen) continue; i -= i % 3; memmove(buf + i + 3, buf + i, maxLen - i - 3); buf[i+1] = ' '; len += 3; } } // end if splitHex mode else { if (len >= maxLen) continue; memmove(buf + i + 1, buf + i, maxLen - i - 1); ++len; } // end else not splitHex mode } else { // overstrike mode if (i >= maxLen) continue; } // end else overstrike mode buf[i++] = key; if (splitHex && (i < maxLen) && (i % 3 == 2)) ++i; if (i > len) len = i; } // end if is acceptable character to insert } // end switch key } // end while not done // Hide the input window & cursor: ConWindow::hideCursor(); inWin.hide(); // Record the result in the history: if (!aborted && len) { String newValue(buf); SVItr exists = find(history.begin(), history.end(), newValue); if (exists != history.end()) // Already in history. Move it to the end: rotate(exists, exists + 1, history.end()); else if (history.size() >= maxHistory) { // History is full. Replace the first entry & move it to the end: history.front().swap(newValue); rotate(history.begin(), history.begin() + 1, history.end()); } else // Just append to history: history.push_back(newValue); } // end if we have a value to store in the history return !aborted;} // end run//--------------------------------------------------------------------// Switch the current input line with one from the history://// Input:// delta: The number to add to historyPos (-1 previous, +1 next)void InputManager::useHistory(int delta){ // Clean up the current string if necessary: normalize(i); // Update the history overlay if necessary: // We always store the initial value, because it doesn't // correspond to a valid entry in history. if (len || historyPos == history.size()) historyOverlay[historyPos].assign(buf, len); // Look for an entry in the overlay: SMItr itr = historyOverlay.find(historyPos += delta); String& s = ((itr == historyOverlay.end()) ? history[historyPos] : itr->second); // Store the new string in the buffer: memset(buf, ' ', maxLen); i = len = min(static_cast<VecSize>(maxLen), s.length()); memcpy(buf, s.c_str(), len);} // end useHistory//--------------------------------------------------------------------// Convert hex string to bytes://// Input:// buf: Must contain a well-formed string of hex characters// (each byte must be separated by spaces)//// Output:// buf: Contains the translated bytes//// Returns:// The number of bytes in bufint packHex(Byte* buf){ unsigned long val; char* in = reinterpret_cast<char*>(buf); Byte* out = buf; while (*in) { if (*in == ' ') ++in; else { val = strtoul(in, &in, 16); *(out++) = Byte(val); } } return out - buf;} // end packHex//--------------------------------------------------------------------// Position the input window://// Input:// cmd: Indicates where the window should be positioned// width: The width of the window// title: The title for the windowvoid positionInWin(Command cmd, short width, const char* title){ inWin.resize(width, 3); inWin.move((screenWidth-width)/2, ((!singleFile && (cmd & cmgGotoBottom)) ? ((cmd & cmgGotoTop) ? numLines + linesBetween // Moving both : numLines + numLines/2 + 1 + linesBetween) // Moving bottom : numLines/2)); // Moving top inWin.border(); inWin.put((width-strlen(title))/2,0, title);} // end positionInWin//--------------------------------------------------------------------// Display prompt window for editing:void showEditPrompt(){ promptWin.clear(); promptWin.border(); promptWin.put(3,1, "Arrow keys move cursor TAB hex\x3C\x3E" "ASCII ESC done"); if (displayTable == ebcdicDisplayTable) promptWin.put(42,1, "EBCDIC"); promptWin.putAttribs( 3,1, cPromptKey, 10); promptWin.putAttribs(33,1, cPromptKey, 3); promptWin.putAttribs(54,1, cPromptKey, 3); if (!singleFile) { promptWin.put(25,2, "RET copy byte from other file"); promptWin.putAttribs(25,2, cPromptKey, 3); } promptWin.update();} // end showEditPrompt//--------------------------------------------------------------------// Display prompt window:void showPrompt(){ promptWin.clear(); promptWin.border();#ifdef WIN32_CONSOLE promptWin.put(1,1, "Arrow keys move F find " "RET next difference ESC quit ALT freeze top"); promptWin.put(1,2, "C ASCII/EBCDIC E edit file " "G goto position Q quit CTRL freeze bottom"); const short topBotLength = 4, topLength = 15;#else // curses promptWin.put(1,1, "Arrow keys move F find " "RET next difference ESC quit T move top"); promptWin.put(1,2, "C ASCII/EBCDIC E edit file " "G goto position Q quit B move bottom"); const short topBotLength = 1, topLength = 10;#endif promptWin.putAttribs( 1,1, cPromptKey, 10); promptWin.putAttribs(18,1, cPromptKey, 1); promptWin.putAttribs(30,1, cPromptKey, 3); promptWin.putAttribs(51,1, cPromptKey, 3); promptWin.putAttribs( 1,2, cPromptKey, 1); promptWin.putAttribs(18,2, cPromptKey, 1); promptWin.putAttribs(32,2, cPromptKey, 1); promptWin.putAttribs(53,2, cPromptKey, 1); if (singleFile) { // Erase "move top" & "move bottom": promptWin.putChar(61,1, ' ', topLength); promptWin.putChar(61,2, ' ', topLength + 3); } else { promptWin.putAttribs(61,1, cPromptKey, topBotLength); promptWin.putAttribs(61,2, cPromptKey, topBotLength); } displayLockState(); displayCharacterSet(); // Calls promptWin.update()} // end showPrompt//--------------------------------------------------------------------// Initialize program://// Returns:// True: Initialization complete// False: Errorbool initialize(){ if (!ConWindow::startup()) return false; ConWindow::hideCursor(); calcScreenLayout(false); inWin.init(0,0, inWidth+2,3, cPromptBdr); inWin.border(); inWin.put((inWidth-4)/2,0, " Goto "); inWin.setAttribs(cPromptWin); inWin.hide(); int y; if (singleFile) y = numLines + 1; else y = numLines * 2 + linesBetween + 2; promptWin.init(0,y, screenWidth,promptHeight, cBackground); showPrompt(); if (!singleFile) diffs.resize(); file1.init(0, (singleFile ? NULL : &diffs)); if (!singleFile) file2.init(numLines + linesBetween + 1, &diffs); return true;} // end initialize//--------------------------------------------------------------------// Get a command from the keyboard://// Returns:// Command code#ifdef WIN32_CONSOLECommand getCommand(){ KEY_EVENT_RECORD e; Command cmd = cmNothing; while (cmd == cmNothing) { ConWindow::readKey(e); switch (safeUC(e.uChar.AsciiChar)) { case KEY_RETURN: // Enter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -