diff --git a/LICENSE b/LICENSE index 45297e0..f25758e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) dd86k 2017 +Copyright (c) dd86k 2017-2019 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 42b3c58..95157a0 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,8 @@ Searching for an ASCII string? Press the return key, or escape, type in `ss IEND` and ddhx will search for "IEND"! Notes: -- Some commands take in sub-command parameters, e.g. `search byte 0xdd`. -- Some commands have _aliases_, e.g. `sb 0xdd` is the same as `search byte 0xdd`. -- Some commands have _multiple definitions_, e.g. `ushort` is the same type as `word` and `w`. +- Some commands take in sub-command parameters, e.g. `search u8 0xdd`. +- Some commands have _aliases_, e.g. `sb 0xdd` is the same as `search u8 0xdd`. - Some commands have a key binded as a command, e.g. pressing `r` while not in command-mode executes the equivelent of `refresh`. Here is a brief list of commands: @@ -56,4 +55,4 @@ ## Screenshots -![ddhx with an ISO file showing information](https://dd86k.github.io/imgs/ddhx3-2.png) \ No newline at end of file +![ddhx showing file information](https://dd86k.github.io/imgs/ddhx3-2.png) \ No newline at end of file diff --git a/docs/ddhx.1 b/docs/ddhx.1 index 9f1fc29..c91773d 100644 --- a/docs/ddhx.1 +++ b/docs/ddhx.1 @@ -2,7 +2,7 @@ ." Please read man-pages(7) and groff_man(7) about the manual page format. ." Don't forget to respect the format of this document! ." -.TH ddhx 1 "July 2017" dd86k "User manual" +.TH ddhx 1 "June 2019" dd86k "User manual" .SH NAME ddhx - Interactive hexadecimal file viewer. @@ -24,7 +24,7 @@ File to open. .IP width -Set width in bytes of the display. +Set width in bytes of the display in bytes. .SH SHORTCUTS @@ -84,12 +84,12 @@ .B Types: .RS .EX -- byte -- short: ushort, word, w -- int: uint, doubleword, dword, dw -- long: ulong, quadword, qword, qw -- string -- wstring +- u8 +- u16 +- u32 +- u64 +- utf8 +- utf16 .EE .RE @@ -106,54 +106,54 @@ Currently, the modifier key states on Posix platforms are unavailable. You are invited to use the .B goto command with the -.BR "end" " and " "start" +.BR "end" " and " "start". aliases. .B .IP Up/Down Arrows -Go backward or forward a line (by width). +Go backward or forward by a line by the screen width in bytes. .B .IP Left/Right Arrow -Go backward or forward a byte +Go backward or forward a byte. .B .IP Home/End -Align to the line +Align to the line by screen width in bytes. .B .IP ^Home/^End Go to begining or end of file. -.SH FILE ATTRIBUTES -The information command will display different file attributes on different platforms: - -.SS Under Windows - -On Windows, the following file attributes (NTFS) will be displayed: -.IP r -Read-only. (FILE_ATTRIBUTE_READONLY) -.IP h -Hidden. (FILE_ATTRIBUTE_HIDDEN) -.IP s -System. (FILE_ATTRIBUTE_SYSTEM) -.IP a -Archive. (FILE_ATTRIBUTE_ARCHIVE) -.IP t -Temporary. (FILE_ATTRIBUTE_TEMPORARY) -.IP S -Sparse file. (FILE_ATTRIBUTE_SPARSE_FILE) -.IP c -Compressed. (FILE_ATTRIBUTE_COMPRESSED) -.IP e -Encrypted. (FILE_ATTRIBUTE_ENCRYPTED) -.RE - -.SS Under Posix-compilant systems - -.RB "The symbolic file permissions are displayed (not exactly like the output of " "ls -l" ")." -The last character is the sticky bit indicator -.RB "('" "t" "')." +.".SH FILE ATTRIBUTES +."The information command will display different file attributes on different platforms: +." +.".SS Under Windows +." +."On Windows, the following file attributes (NTFS) will be displayed: +.".IP r +."Read-only. (FILE_ATTRIBUTE_READONLY) +.".IP h +."Hidden. (FILE_ATTRIBUTE_HIDDEN) +.".IP s +."System. (FILE_ATTRIBUTE_SYSTEM) +.".IP a +."Archive. (FILE_ATTRIBUTE_ARCHIVE) +.".IP t +."Temporary. (FILE_ATTRIBUTE_TEMPORARY) +.".IP S +."Sparse file. (FILE_ATTRIBUTE_SPARSE_FILE) +.".IP c +."Compressed. (FILE_ATTRIBUTE_COMPRESSED) +.".IP e +."Encrypted. (FILE_ATTRIBUTE_ENCRYPTED) +.".RE +." +.".SS Under Posix-compilant systems +." +.".RB "The symbolic file permissions are displayed (not exactly like the output of " "ls -l" ")." +."The last character is the sticky bit indicator +.".RB "('" "t" "')." .SH WARNINGS ddhx is still currently going under active development. Expect lots of bugs and crashes! @@ -172,7 +172,7 @@ Homepage: .UE -.MT devddstuff@gmail.com +.MT dd@dax.moe Email: .ME diff --git a/dub.sdl b/dub.sdl index 8a62cc5..32504ed 100644 --- a/dub.sdl +++ b/dub.sdl @@ -1,5 +1,5 @@ name "ddhx" -description "DD's hexadecimal File Viewer" +description "Hexadecimal file viewer" authors "dd86k" -copyright "Copyright © 2017 dd86k" +copyright "Copyright © 2017-2019 dd86k" license "MIT" \ No newline at end of file diff --git a/src/Menu.d b/src/Menu.d index 55563ff..6c6e6d6 100644 --- a/src/Menu.d +++ b/src/Menu.d @@ -9,16 +9,15 @@ //TODO: count command (stat) //TODO: Invert aliases /*TODO: Aliases - si: Search int - sl: Search long - utf8: search utf-8 string, etc. + su32: Search int + su64: Search long */ /** * Internal command prompt. - * Params: init = Initial command + * Params: prepend = Initial command */ -void Menu(string prepend = null) { +void hxmenu(string prepend = null) { import std.array : split; import std.algorithm.iteration : splitter; import std.algorithm.sorting : merge; @@ -26,170 +25,153 @@ import std.algorithm : joiner; import std.format : sformat; - ClearMsg; - SetPos(0, 0); + screenpos(0, 0); + printf("%*s", screenwidth - 1, cast(char*)" "); + screenpos(0, 0); printf(">"); if (prepend) write(prepend); -// char[] inbuf = void; +// size_t argc; +// char[1024] inbuf = void; +// string[12] argv = void; // const size_t inbufl = readln(inbuf); //TODO: GC-free merge prepend and readln(buf), then split - string[] e = cast(string[])(prepend ~ readln[0..$-1]).split; // split ' ', no empty entries + string[] argv = cast(string[])(prepend ~ readln[0..$-1]).split; // split ' ', no empty entries - UpdateOffsetBar; - const size_t argl = e.length; - if (argl == 0) return; + hxoffsetbar; - switch (e[0]) { + const size_t argc = argv.length; + if (argc == 0) return; + + switch (argv[0]) { case "g", "goto": - if (argl > 1) { - switch (e[1]) { - case "e", "end": - Goto(fsize - screenl); - break; - case "h", "home", "s": - Goto(0); - break; - default: - GotoStr(e[1]); - } + if (argc <= 1) { + msgalt("Missing position (number)"); + break; + } + switch (argv[1]) { + case "e", "end": + hxgoto(fsize - screenl); + break; + case "h", "home": + hxgoto(0); + break; + default: + gotostr(argv[1]); } break; case "s", "search": // Search - if (argl <= 1) break; - - string value = e[$ - 1]; - const bool a2 = argl > 2; - bool invert; - if (a2) invert = e[2] == "invert"; - switch (e[1]) { - case "u8": - if (argl > 2) { - e[1] = value; - goto SEARCH_BYTE; - } else - MessageAlt("Missing argument. (Byte)"); + if (argc <= 1) { + msgalt("Missing data type"); break; + } + if (argc <= 2) { + msgalt("Missing data argument"); + break; + } + + string value = argv[2]; + switch (argv[1]) { + case "u8": + argv[1] = value; + goto SEARCH_BYTE; case "u16": - if (argl > 2) { - search_u16(value, invert); - } else - MessageAlt("Missing argument. (Number)"); + search_u16(value); break; case "u32": - if (argl > 2) { - search_u32(value, invert); - } else - MessageAlt("Missing argument. (Number)"); + search_u32(value); break; case "u64": - if (argl > 2) { - search_u64(value, invert); - } else - MessageAlt("Missing argument. (Number)"); + search_u64(value); break; case "utf8": - if (argl > 2) - search_utf8(value); - else - MessageAlt("Missing argument. (String)"); + search_utf8(value); break; case "utf16": - if (argl > 2) - search_utf16(value, invert); - else - MessageAlt("Missing argument. (String)"); + search_utf16(value); break; default: - MessageAlt( - argl > 1 ? "Invalid type." : "Missing type." - ); + msgalt("Invalid type (%s)", argv[1]); break; } break; // "search" case "ss": // Search ASCII/UTF-8 string - if (argl > 1) - search_utf8(e[1]); + if (argc > 1) + search_utf8(argv[1]); else - MessageAlt("Missing argument. (String)"); + msgalt("Missing argument (utf8)"); break; case "sw": // Search UTF-16 string - if (argl > 1) - search_utf16(e[1]); + if (argc > 1) + search_utf16(argv[1]); else - MessageAlt("Missing argument. (String)"); + msgalt("Missing argument (utf16)"); break; //TODO: UTF-32 search alias case "sb": // Search byte SEARCH_BYTE: - if (argl > 1) { - import utils : unformat; - long l; - if (unformat(e[1], l)) { - search_u8(l & 0xFF); - } else { - MessageAlt("Could not parse number"); - } + if (argc <= 1) { + msgalt("Missing argument (u8)"); + break; + } + import utils : unformat; + long l; + if (unformat(argv[1], l)) { + search_u8(l & 0xFF); + } else { + msgalt("Could not parse number"); } break; - case "i", "info": PrintFileInfo; break; + case "i", "info": hxfileinfo; break; case "o", "offset": - if (argl > 1) { - import settings : HandleOffset; - HandleOffset(e[1]); - UpdateOffsetBar; - UpdateDisplayRawMM; + import settings : HandleOffset; + if (argc <= 1) { + msgalt("Missing offset"); + break; } + HandleOffset(argv[1]); + hxoffsetbar; + hxupdate_r; break; - case "clear": - Clear; - UpdateOffsetBar; - UpdateDisplayRawMM; - UpdateInfoBarRaw; + case "refresh": hxrefresh_a; break; + case "quit": hxexit; break; + case "about": + msgalt("Written by dd86k. Copyright (c) dd86k 2017-2019"); + break; + case "version": + enum V = "Using ddhx " ~ APP_VERSION; + msgalt(V); break; // // Setting manager // case "set": - if (argl <= 1) { - MessageAlt("Missing setting parameter"); + if (argc <= 1) { + msgalt("Missing setting"); break; } - import std.format : format; - switch (e[1]) { + if (argc <= 2) { + msgalt("Missing setting option"); + break; + } + switch (argv[1]) { case "width", "w": - if (argl > 2) { - HandleWidth(e[2]); - PrepBuffer; - RefreshAll; - } + HandleWidth(argv[2]); + hxprep; + hxrefresh_a; break; case "offset", "o": - if (argl > 2) { - HandleOffset(e[2]); - Clear; - RefreshAll; - } + HandleOffset(argv[2]); + screenclear; + hxrefresh_a; break; default: - MessageAlt("Unknown setting parameter: %s", e[1]); + msgalt("Unknown setting: %s", argv[1]); break; } break; - case "refresh": RefreshAll; break; - case "quit": Exit; break; - case "about": ShowAbout; break; - case "version": ShowInfo; break; - default: MessageAlt("Unknown command: %s", e[0]); break; + default: msgalt("Unknown command: %s", argv[0]); break; } -} - -private void ShowAbout() { - MessageAlt("Written by dd86k. Copyright (c) dd86k 2017-2019"); -} - -private void ShowInfo() { - MessageAlt("Using ddhx " ~ APP_VERSION); // const string } \ No newline at end of file diff --git a/src/Searcher.d b/src/Searcher.d index 6566ad7..c1dbb83 100644 --- a/src/Searcher.d +++ b/src/Searcher.d @@ -67,10 +67,10 @@ * Params: b = ubyte */ void search_u8(const ubyte b) { - MessageAlt("Searching byte..."); + msgalt("Searching byte..."); ubyte[1] a = [ b ]; search_arr(a, "byte"); - MessageAlt("Byte not found"); + msgalt("Byte not found"); } /** @@ -87,7 +87,7 @@ *(cast(ushort*)la) = u16; search_arr(la, "u16"); } else - MessageAlt("Could not parse number"); + msgalt("Could not parse number"); } /** @@ -104,7 +104,7 @@ *(cast(uint*)la) = u32; search_arr(la, "u32"); } else - MessageAlt("Could not parse number"); + msgalt("Could not parse number"); } /** @@ -121,11 +121,11 @@ *(cast(long*)la) = l; search_arr(la, "u64"); } else - MessageAlt("Could not parse number"); + msgalt("Could not parse number"); } private void search_arr(ubyte[] data, string type) { - MessageAlt(" Searching %s", type); + msgalt(" Searching %s", type); const ubyte firstbyte = data[0]; const size_t datal = data.length; long pos = fpos + 1; // To not affect file position itself @@ -138,7 +138,7 @@ const size_t ilen = i + datal; if (ilen < bufl) { // Within CHUNK if (buf[i..i+datal] == data) { - GotoC(pos + i); + hxgoto_c(pos + i); return; } } else if (ilen < fsize) { // Out-of-chunk @@ -152,5 +152,5 @@ } pos += CHUNK_SIZE; } - MessageAlt(" Not found (%s)", type); + msgalt(" Not found (%s)", type); } \ No newline at end of file diff --git a/src/ddcon.d b/src/ddcon.d index 1f999ad..a214261 100644 --- a/src/ddcon.d +++ b/src/ddcon.d @@ -31,13 +31,14 @@ private __gshared termios old_tio, new_tio; } +extern (C): + /******************************************************************* * Initiation *******************************************************************/ /// Initiate ddcon -extern (C) -void InitConsole() { +void screeninit() { version (Windows) { hOut = GetStdHandle(STD_OUTPUT_HANDLE); hIn = GetStdHandle(STD_INPUT_HANDLE); @@ -54,8 +55,7 @@ *******************************************************************/ /// Clear screen -extern (C) -void Clear() { +void screenclear() { version (Windows) { CONSOLE_SCREEN_BUFFER_INFO csbi = void; COORD c; @@ -65,7 +65,7 @@ if (FillConsoleOutputCharacterA(hOut, ' ', size, c, &num) == 0 /*|| // .NET uses this but no idea why yet. FillConsoleOutputAttribute(hOut, csbi.wAttributes, size, c, &num) == 0*/) { - SetPos(0, 0); + screenpos(0, 0); } else // If that fails, run cls. sys ("cls"); @@ -83,7 +83,7 @@ /// Window width /// Returns: Window width in characters -@property ushort WindowWidth() { +@property ushort screenwidth() { version (Windows) { CONSOLE_SCREEN_BUFFER_INFO c = void; GetConsoleScreenBufferInfo(hOut, &c); @@ -99,7 +99,7 @@ /// Window height /// Returns: Window height in characters -@property ushort WindowHeight() { +@property ushort screenheight() { version (Windows) { CONSOLE_SCREEN_BUFFER_INFO c = void; GetConsoleScreenBufferInfo(hOut, &c); @@ -124,8 +124,7 @@ * x = X position (horizontal) * y = Y position (vertical) */ -extern (C) -void SetPos(int x, int y) { +void screenpos(int x, int y) { version (Windows) { // 0-based __gshared COORD c = void; c.X = cast(short)x; @@ -145,8 +144,7 @@ * Params: * k = KeyInfo struct */ -extern (C) -void ReadKey(ref KeyInfo k) { +void screenkey(ref KeyInfo k) { version (Windows) { // Sort of is like .NET's ReadKey INPUT_RECORD ir = void; DWORD num = void; diff --git a/src/ddhx.d b/src/ddhx.d index 41bcfb9..1f8e4b5 100644 --- a/src/ddhx.d +++ b/src/ddhx.d @@ -60,34 +60,34 @@ // Internal // -__gshared MmFile MMFile = void; -__gshared ubyte* mmbuf = void; -__gshared uint screenl = void; // screen size +__gshared MmFile MMFile = void; /// Main mmfile +__gshared ubyte* mmbuf = void; /// mmfile buffer address +__gshared uint screenl = void; /// screen size -__gshared string fname = void; -__gshared long fpos = void; /// Current file position -__gshared long fsize = void; /// File size +__gshared string fname = void; /// filename +__gshared long fpos = void; /// Current file position +__gshared long fsize = void; /// File size -private __gshared char[30] tfsizebuf; /// total formatted size buffer -private __gshared char[] tfsize; /// total formatted size (pointer) +private __gshared char[30] tfsizebuf; /// total formatted size buffer +private __gshared char[] tfsize; /// total formatted size (pointer) /// Main app entry point void Start() { fpos = 0; tfsize = formatsize(tfsizebuf, fsize); - InitConsole; - PrepBuffer; - Clear; - UpdateOffsetBar; - UpdateDisplayRawMM; - UpdateInfoBarRaw; + screeninit; + hxprep; + screenclear; + hxoffsetbar; + hxupdate_r; + hxinfobar_r; KeyInfo k = void; KEY: - ReadKey(k); + screenkey(k); //TODO: Handle resize event if (k.keyCode) - HandleKey(k); + hxkey(k); goto KEY; } @@ -118,7 +118,7 @@ * Params: k = KeyInfo (ddcon) */ extern (C) -void HandleKey(const ref KeyInfo k) { +void hxkey(const ref KeyInfo k) { import settings : HandleWidth; switch (k.keyCode) { @@ -129,55 +129,55 @@ case Key.UpArrow: if (fpos - BytesPerRow >= 0) - Goto(fpos - BytesPerRow); + hxgoto(fpos - BytesPerRow); else - Goto(0); + hxgoto(0); break; case Key.DownArrow: if (fpos + screenl + BytesPerRow <= fsize) - Goto(fpos + BytesPerRow); + hxgoto(fpos + BytesPerRow); else - Goto(fsize - screenl); + hxgoto(fsize - screenl); break; case Key.LeftArrow: if (fpos - 1 >= 0) // Else already at 0 - Goto(fpos - 1); + hxgoto(fpos - 1); break; case Key.RightArrow: if (fpos + screenl + 1 <= fsize) - Goto(fpos + 1); + hxgoto(fpos + 1); else - Goto(fsize - screenl); + hxgoto(fsize - screenl); break; case Key.PageUp: if (fpos - cast(long)screenl >= 0) - Goto(fpos - screenl); + hxgoto(fpos - screenl); else - Goto(0); + hxgoto(0); break; case Key.PageDown: if (fpos + screenl + screenl <= fsize) - Goto(fpos + screenl); + hxgoto(fpos + screenl); else - Goto(fsize - screenl); + hxgoto(fsize - screenl); break; case Key.Home: if (k.ctrl) - Goto(0); + hxgoto(0); else - Goto(fpos - (fpos % BytesPerRow)); + hxgoto(fpos - (fpos % BytesPerRow)); break; case Key.End: if (k.ctrl) - Goto(fsize - screenl); + hxgoto(fsize - screenl); else { const long np = fpos + (BytesPerRow - fpos % BytesPerRow); if (np + screenl <= fsize) - Goto(np); + hxgoto(np); else - Goto(fsize - screenl); + hxgoto(fsize - screenl); } break; @@ -186,45 +186,45 @@ // case Key.Escape, Key.Enter: - Menu; + hxmenu; break; case Key.G: - Menu("g "); - UpdateOffsetBar(); + hxmenu("g "); + hxoffsetbar(); break; case Key.I: - PrintFileInfo; + hxfileinfo; break; case Key.R, Key.F5: - RefreshAll; + hxrefresh_a; break; case Key.A: HandleWidth("a"); - RefreshAll; + hxrefresh_a; break; - case Key.Q: Exit; break; + case Key.Q: hxexit; break; default: } } /// Refresh the entire screen extern (C) -void RefreshAll() { - PrepBuffer; - Clear; - UpdateOffsetBar; - UpdateDisplayRawMM; - UpdateInfoBarRaw; +void hxrefresh_a() { + hxprep; + screenclear; + hxoffsetbar; + hxupdate_r; + hxinfobar_r; } /** * Update the upper offset bar. */ extern (C) -void UpdateOffsetBar() { +void hxoffsetbar() { char [8]format = cast(char[8])" %02X"; // default format[4] = formatTable[CurrentOffsetType]; - SetPos(0, 0); + screenpos(0, 0); printf("Offset %c ", offsetTable[CurrentOffsetType]); for (ushort i; i < BytesPerRow; ++i) printf(cast(char*)format, i); @@ -233,14 +233,14 @@ /// Update the bottom current information bar. extern (C) -void UpdateInfoBar() { - SetPos(0, WindowHeight - 1); - UpdateInfoBarRaw; +void hxinfobar() { + screenpos(0, screenheight - 1); + hxinfobar_r; } /// Updates information bar without cursor position call. extern (C) -void UpdateInfoBarRaw() { +void hxinfobar_r() { char[30] bl = void, cp = void; writef(" %*s | %*s/%*s | %7.3f%%", 7, formatsize(bl, screenl), // Buffer size @@ -252,8 +252,8 @@ /// Determine screensize extern (C) -void PrepBuffer() { - const int bufs = (WindowHeight - 2) * BytesPerRow; // Proposed buffer size +void hxprep() { + const int bufs = (screenheight - 2) * BytesPerRow; // Proposed buffer size screenl = fsize >= bufs ? bufs : cast(uint)fsize; } @@ -264,13 +264,13 @@ * Params: pos = New position */ extern (C) -void Goto(long pos) { +void hxgoto(long pos) { if (screenl < fsize) { fpos = pos; - UpdateDisplay; - UpdateInfoBarRaw; + hxupdate; + hxinfobar_r; } else - MessageAlt("Navigation disabled, buffer too small."); + msgalt("Navigation disabled, buffer too small."); } /** @@ -279,11 +279,11 @@ * Params: pos = New position */ extern (C) -void GotoC(long pos) { +void hxgoto_c(long pos) { if (pos + screenl > fsize) - Goto(fsize - screenl);//Buffer.length); + hxgoto(fsize - screenl);//Buffer.length); else - Goto(pos); + hxgoto(pos); } /** @@ -291,7 +291,7 @@ * Includes offset checking (+/- notation). * Params: str = String as a number */ -void GotoStr(string str) { +void gotostr(string str) { byte rel; // Lazy code if (str[0] == '+') { rel = 1; @@ -301,39 +301,39 @@ str = str[1..$]; } long l = void; - if (unformat(str, l)) { - switch (rel) { - case 1: - if (fpos + l - screenl < fsize) - Goto(fpos + l); - break; - case 2: - if (fpos - l >= 0) - Goto(fpos - l); - break; - default: - if (l >= 0 && l < fsize - screenl) { - Goto(l); - } else { - import std.format : format; - MessageAlt(format("Range too far or negative: %d (%XH)", l, l)); - } + if (unformat(str, l) == false) { + msgalt("Could not parse number"); + return; + } + switch (rel) { + case 1: + if (fpos + l - screenl < fsize) + hxgoto(fpos + l); + break; + case 2: + if (fpos - l >= 0) + hxgoto(fpos - l); + break; + default: + if (l >= 0 && l < fsize - screenl) { + hxgoto(l); + } else { + import std.format : format; + msgalt(format("Range too far or negative: %d (%XH)", l, l)); } - } else { - MessageAlt("Could not parse number"); } } /// Update display from buffer extern (C) -void UpdateDisplay() { - SetPos(0, 1); - UpdateDisplayRawMM; +void hxupdate() { + screenpos(0, 1); + hxupdate_r; } /// Update display from buffer without setting cursor extern (C) -void UpdateDisplayRawMM() { +void hxupdate_r() { import core.stdc.string : memset; char [1024]a = void; char [1024]d = void; @@ -350,7 +350,7 @@ //TODO: if >fsize, then slice differently ubyte[] fbuf = cast(ubyte[])MMFile[p..blen]; - char [16]bytef = cast(char[16])"%08X %s %s\n"; + char [32]bytef = cast(char[32])"%08X %s %s\n"; bytef[3] = formatTable[CurrentOffsetType]; for (size_t bi; p < blen; p += brow) { @@ -367,7 +367,7 @@ d[di++] = ' '; d[di++] = hexTable[b >> 4]; d[di++] = hexTable[b & 15]; - a[ai] = FormatChar(b); + a[ai] = fchar(b); } printf(cast(char*)bytef, p, cast(char*)d, cast(char*)a); @@ -380,58 +380,45 @@ * Message once (upper bar) * Params: msg = Message string */ -void Message(string msg) { - ClearMsg; - SetPos(0, 0); - write(msg); -} - -/// Clear upper bar -extern (C) -void ClearMsg() { - SetPos(0, 0); - writef("%*s", WindowWidth - 1, " "); +void msg(string msg) { + screenpos(0, 0); + writef("%s%*s", msg, (screenwidth - 1) - msg.length, " "); } /** * Message once (bottom bar) * Params: msg = Message string */ -void MessageAlt(string msg) { - ClearMsgAlt; - SetPos(0, WindowHeight - 1); - write(msg); +void msgalt(string msg) { + screenpos(0, screenheight - 1); + writef("%s%*s", msg, (screenwidth - 1) - msg.length, " "); } -void MessageAlt(string f, string arg) { +/** + * Bottom bar message. + * Params: + * f = Format + * arg = String argument + */ +void msgalt(string f, string arg) { import std.format : format; - MessageAlt(format(f, arg)); -} - -/// Clear bottom bar -extern (C) -void ClearMsgAlt() { - SetPos(0, WindowHeight - 1); - writef("%*s", WindowWidth - 1, " "); + msgalt(format(f, arg)); } /// Print some file information at the bottom bar extern (C) -void PrintFileInfo() { +void hxfileinfo() { import std.format : sformat; import std.path : baseName; - char[512] b = void; - - ClearMsgAlt; - MessageAlt(cast(string)b.sformat!"%s %s"(tfsize, fname.baseName)); + msgalt(cast(string)b.sformat!"%s %s"(tfsize, fname.baseName)); } /// Exits ddhx extern (C) -void Exit() { +void hxexit() { import core.stdc.stdlib : exit; - Clear; + screenclear; exit(0); } @@ -442,6 +429,6 @@ * Returns: ASCII character */ extern (C) -char FormatChar(ubyte c) pure @safe @nogc nothrow { //TODO: EIBEC? +char fchar(ubyte c) pure @safe @nogc nothrow { //TODO: EIBEC? return c > 0x7E || c < 0x20 ? DEFAULT_CHAR : c; } \ No newline at end of file diff --git a/src/main.d b/src/main.d index ac577c7..3d6695b 100644 --- a/src/main.d +++ b/src/main.d @@ -22,14 +22,14 @@ writeln( `Interactive hexadecimal file viewer. Usage: - ddhx [Options] file - ddhx {-h|--help|-v|--version} + ddhx [OPTIONS] file + ddhx {-h|--help|--version} -Option Description - -w Set the number of bytes per line, 'a' being automatic - -o Set offset type - -v, --version Print version screen and quit - -h, --help Print help screen and quit` +Option Description + -w Set the number of bytes per line, 'a' being automatic + -o Set offset type + --version Print version screen and quit + -h, --help Print help screen and quit` ); exit(0); } @@ -48,42 +48,42 @@ } int main(string[] args) { - - if (args.length <= 1) // FILE required + if (args.length <= 1) // FILE or OPTION required phelp; - GetoptResult r = void; try { - r = getopt(args, - "w", "Set the number of bytes per line, 'a' being automatic.", &HandleWCLI, - "o", "Set offset type.", &HandleOCLI, - "version", "Print version information.", &pversion); + args.getopt( + config.caseSensitive, + "w", &HandleWCLI, + config.caseSensitive, + "o", &HandleOCLI, + config.caseSensitive, + "h|help", &phelp, + config.caseSensitive, + "version", &pversion + ); } catch (GetOptException ex) { stderr.writefln("%s, aborting", ex.msg); return 1; } - if (r.helpWanted) - phelp; - string file = args[$ - 1]; - if (file.exists) { - if (file.isDir) { - stderr.writefln(`"%s" is a directory, aborting`, file); - return 3; - } - - MMFile = new MmFile((fname = file), MmFile.Mode.read, 0, mmbuf); - - if ((fsize = MMFile.length) <= 0) { - stderr.writeln("Empty file, aborting"); - return 4; - } - } else { + if (file.exists == false) { stderr.writefln(`File "%s" doesn't exist, aborting`, file); return 2; } + if (file.isDir) { + stderr.writefln(`"%s" is a directory, aborting`, file); + return 3; + } + + MMFile = new MmFile((fname = file), MmFile.Mode.read, 0, mmbuf); + + if ((fsize = MMFile.length) <= 0) { + stderr.writeln("Empty file, aborting"); + return 4; + } Start; // start ddhx return 0; diff --git a/src/settings.d b/src/settings.d index b837377..84bd256 100644 --- a/src/settings.d +++ b/src/settings.d @@ -49,7 +49,7 @@ writefln(ETRANGE, l, ushort.max); exit(1); } else - MessageAlt("Number out of range"); + msgalt("Number out of range"); return; } BytesPerRow = l & 0xFFFF; @@ -58,7 +58,7 @@ writeln(ENOPARSE); exit(1); } else - MessageAlt(ENOPARSE); + msgalt(ENOPARSE); } } } @@ -89,19 +89,19 @@ writef("Unknown mode parameter: %s", val); exit(1); } else { - MessageAlt(format(" Invalid offset type: %s", val)); + msgalt(format(" Invalid offset type: %s", val)); } break; } } private ushort getBytesPerRow() { - import ddcon : WindowWidth; + import ddcon : screenwidth; final switch (CurrentDisplayMode) { case DisplayMode.Default: - return cast(ushort)((WindowWidth - 11) / 4); + return cast(ushort)((screenwidth - 11) / 4); case DisplayMode.Text, DisplayMode.Data: - return cast(ushort)((WindowWidth - 11) / 3); + return cast(ushort)((screenwidth - 11) / 3); } } \ No newline at end of file