1/* 2 3 Minimum Profit - A Text Editor 4 Hexadecimal viewer. 5 6 ttcdt <dev@triptico.com> et al. 7 8 This software is released into the public domain. 9 NO WARRANTY. See file LICENSE for details. 10 11*/ 12 13/** hexadecimal viewer object **/ 14 15global mp_hex_view = new(mp_base, { 16 name: '<hex view>', 17 offset: 0, 18 tx: 0, 19 bpl: 8, 20 data: '', 21 f_offset: 0, 22 f_size: 0, 23 fd: NULL, 24 25 get_status: sub (hex) { 26 sprintf("%s - 0x%06x (%d)", name, offset, offset); 27 }, 28 init: sub (hex) { 29 if ((fd = open(name, "rb")) == NULL) 30 hex = NULL; 31 32 name = sprintf(L("<hex view of %s>"), name); 33 34 return hex; 35 }, 36 keypress: sub (hex, keycode) { 37 if (keycode == 'cursor-down') 38 offset += bpl; 39 else 40 if (keycode == 'cursor-up') 41 offset -= bpl; 42 else 43 if (keycode == 'page-down' || keycode == 'mouse-wheel-down') 44 offset += bpl * (mp.window.ty - 1); 45 else 46 if (keycode == 'page-up' || keycode == 'mouse-wheel-up') 47 offset -= bpl * (mp.window.ty - 1); 48 else 49 if (keycode == 'home') 50 offset = 0; 51 else 52 if (keycode == 'end') { 53 fseek(fd, 0, 2); 54 offset = ftell(fd); 55 } 56 57 if (offset < 0) 58 offset = 0; 59 60 fseek(fd, 0, 2); 61 if (offset >= ftell(fd)) 62 offset = ftell(fd); 63 64 return hex; 65 }, 66 render: sub (hex) { 67 local out = []; 68 local o; 69 70 if (tx != mp.window.tx) { 71 /* calculate bytes per line */ 72 bpl = 100; 73 74 while ((12 + (bpl * 4)) > mp.window.tx) 75 bpl -= 1; 76 77 tx = mp.window.tx; 78 } 79 80 /* round offset */ 81 offset -= offset % bpl; 82 83 fseek(fd, offset, 0); 84 85 o = offset; 86 87 while (size(out) < mp.window.ty) { 88 local ov, nv, av, n, c; 89 90 nv = []; 91 av = [ 92 mp.colors.word2.attr, 93 ' | ' 94 ]; 95 ov = [ 96 mp.colors.word1.attr, 97 sprintf(" %06X |", ftell(fd)) 98 ]; 99 100 for (n = 0; n < bpl; n += 1) { 101 local a = 0; 102 103 if ((c = getchar(fd)) == NULL) { 104 n -= 1; 105 break; 106 } 107 108 if (o >= f_offset && o < f_offset + f_size) 109 a = mp.colors.search.attr; 110 else 111 a = mp.colors.normal.attr; 112 113 if (o == f_offset) 114 push(nv, mp.colors.normal.attr, ' ', 115 a, sprintf("%02X", ord(c))); 116 else 117 push(nv, a, sprintf(" %02X", ord(c))); 118 119 if (ord(c) == 0x0a) 120 c = mp.unicode("pilcrow"); 121 else 122 if (ord(c) < 32 || ord(c) > 126) 123 c = mp.unicode("middledot"); 124 125 push(av, a, c); 126 127 o += 1; 128 } 129 130 while (n < bpl) { 131 push(nv, mp.colors.normal.attr, ' '); 132 push(av, mp.colors.word2.attr, ' '); 133 n += 1; 134 } 135 136 push(out, ov->join(nv)->join(av)); 137 138 if (c == NULL) 139 break; 140 } 141 142 while (size(out) < mp.window.ty) 143 push(out, []); 144 145 return out; 146 }, 147 actions: { 148 seek_next: sub (hex) { 149 fseek(hex.fd, hex.f_offset + 1); 150 151 mp.busy(1); 152 local found = mp_c.search_hex(hex.fd, hex.data); 153 mp.busy(0); 154 155 if (found) { 156 hex.f_offset = ftell(hex.fd); 157 hex.f_size = hex.data->size() / 2; 158 hex.offset = hex.f_offset; 159 } 160 else 161 mp.alert(L("Not found.")); 162 }, 163 164 seek: sub (hex) { 165 local t = mp.form( 166 [ 167 { 168 label: L("Hex string to seek") + ':', 169 type: 'text', 170 history: 'search-hex' 171 } 172 ] 173 ); 174 175 if (t != NULL) { 176 hex.data = t[0]; 177 hex.f_offset = hex.offset - 1; 178 hex->actions.seek_next(); 179 } 180 } 181 }, 182 keycodes: { 183 "ctrl-f" => 'seek', 184 "f3" => 'seek_next' 185 } 186 } 187); 188