update README
[rofl0r-hexedit0r.git] / display.c
blob888da1d262526a0b647358491e2abc5864d074ab
1 /* hexedit -- Hexadecimal Editor for Binary Files
2 Copyright (C) 1998 Pixel (Pascal Rigaux)
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/
17 #include "hexedit.h"
19 int have_colors;
21 int move_cursor(off_t delta)
23 return set_cursor(base + cursor + delta);
26 int set_cursor(off_t loc)
28 if (loc < 0 && base % lineLength)
29 loc = 0;
31 if (!tryloc(loc))
32 return FALSE;
34 if (loc < base) {
35 if (loc - base % lineLength < 0)
36 set_base(0);
37 else if (!move_base(myfloor(loc - base % lineLength, lineLength) + base % lineLength - base))
38 return FALSE;
39 cursor = loc - base;
40 } else if (loc >= base + page) {
41 if (!move_base(myfloor(loc - base % lineLength, lineLength) + base % lineLength - page + lineLength - base))
42 return FALSE;
43 cursor = loc - base;
44 } else if (loc > base + nbBytes) {
45 return FALSE;
46 } else
47 cursor = loc - base;
49 if (mark_set)
50 updateMarked();
52 return TRUE;
55 int move_base(off_t delta)
57 if (mode == bySector) {
58 if (delta > 0 && delta < page)
59 delta = page;
60 else if (delta < 0 && delta > -page)
61 delta = -page;
63 return set_base(base + delta);
66 int set_base(off_t loc)
68 if (loc < 0) loc = 0;
70 if (!tryloc(loc)) return FALSE;
71 base = loc;
72 readFile();
74 if (mode != bySector && nbBytes < page - lineLength && base != 0) {
75 base -= myfloor(page - nbBytes - lineLength, lineLength);
76 if (base < 0) base = 0;
77 readFile();
80 if (cursor > nbBytes) cursor = nbBytes;
81 return TRUE;
85 int computeLineSize(void) { return computeCursorXPos(lineLength - 1, 0) + 1; }
86 int computeCursorXCurrentPos(void) { return computeCursorXPos(cursor, hexOrAscii); }
87 int computeCursorXPos(int cursor, int hexOrAscii)
89 int r = 11;
90 int x = cursor % lineLength;
91 int h = (hexOrAscii ? x : lineLength - 1);
93 r += normalSpaces * (h % blocSize) + (h / blocSize) * (normalSpaces * blocSize + 1) + (hexOrAscii && cursorOffset);
95 if (!hexOrAscii) r += x + normalSpaces + 1;
97 return r;
102 /*******************************************************************************/
103 /* Curses functions */
104 /*******************************************************************************/
105 void initCurses(void)
107 initscr();
108 have_colors = has_colors();
109 if (have_colors && colored) {
110 start_color();
111 use_default_colors();
112 init_pair(1, COLOR_RED, -1); /* null zeros */
113 init_pair(2, COLOR_GREEN, -1); /* control chars */
114 init_pair(3, COLOR_BLUE, -1); /* extended chars */
117 refresh();
118 raw();
119 noecho();
120 keypad(stdscr, TRUE);
122 if (mode == bySector) {
123 lineLength = modes[bySector].lineLength;
124 page = modes[bySector].page;
125 page = myfloor((LINES - 1) * lineLength, page);
126 blocSize = modes[bySector].blocSize;
127 if (computeLineSize() > COLS) DIE("%s: term is too small for sectored view (width)\n");
128 if (page == 0) DIE("%s: term is too small for sectored view (height)\n");
129 } else { /* mode == maximized */
130 if (LINES <= 4) DIE("%s: term is too small (height)\n");
132 blocSize = modes[maximized].blocSize;
133 for (lineLength = blocSize; computeLineSize() <= COLS; lineLength += blocSize);
134 lineLength -= blocSize;
135 if (lineLength == 0) DIE("%s: term is too small (width)\n");
137 page = lineLength * (LINES - 1);
139 colsUsed = computeLineSize();
140 buffer = malloc(page);
141 bufferAttr = malloc(page * sizeof(*bufferAttr));
144 void exitCurses(void)
146 close(fd);
147 clear();
148 refresh();
149 endwin();
152 void display(void)
154 int i;
156 for (i = 0; i < nbBytes; i += lineLength) {
157 move(i / lineLength, 0);
158 displayLine(i, nbBytes);
160 for (; i < page; i += lineLength) {
161 int j;
162 move(i / lineLength, 0);
163 for (j = 0; j < colsUsed; j++) printw(" "); /* cleanup the line */
164 move(i / lineLength, 0);
165 PRINTW(("%08lX", (int) (base + i)));
168 attrset(NORMAL);
169 move(LINES - 1, 0);
170 for (i = 0; i < colsUsed; i++) printw("-");
171 move(LINES - 1, 0);
172 if (isReadOnly) i = '%';
173 else if (edited) i = '*';
174 else i = '-';
175 printw("-%c%c %s --0x%llX", i, i, baseName, (long long) base + cursor);
176 if (MAX(fileSize, lastEditedLoc)) printw("/0x%llX", (long long) getfilesize());
177 if (mode == bySector) printw("--sector %lld", (long long) (base + cursor) / SECTOR_SIZE);
179 move(cursor / lineLength, computeCursorXCurrentPos());
182 void displayLine(int offset, int max)
184 int i;
186 PRINTW(("%08lX ", (int) (base + offset)));
187 for (i = offset; i < offset + lineLength; i++) {
188 if (i > offset) MAXATTRPRINTW(bufferAttr[i] & MARKED, (((i - offset) % blocSize) ? " " : " "));
189 if (i < max) {
190 ATTRPRINTW(
191 (!(have_colors && colored) ? 0 :
192 buffer[i] == 0 ? COLOR_PAIR(1) :
193 buffer[i] < ' ' ? COLOR_PAIR(2) :
194 buffer[i] >= 127 ? COLOR_PAIR(3) : 0) |
195 bufferAttr[i], ("%02X", buffer[i]));
197 else PRINTW((" "));
199 PRINTW((" "));
200 for (i = offset; i < offset + lineLength; i++) {
201 if (i >= max) PRINTW((" "));
202 else if (buffer[i] >= ' ' && buffer[i] < 127) ATTRPRINTW(bufferAttr[i], ("%c", buffer[i]));
203 else ATTRPRINTW(bufferAttr[i], ("."));
207 void clr_line(int line) { move(line, 0); clrtoeol(); }
209 void displayCentered(char *msg, int line)
211 clr_line(line);
212 move(line, (COLS - strlen(msg)) / 2);
213 PRINTW(("%s", msg));
216 void displayOneLineMessage(char *msg)
218 int center = page / lineLength / 2;
219 clr_line(center - 1);
220 clr_line(center + 1);
221 displayCentered(msg, center);
224 void displayTwoLineMessage(char *msg1, char *msg2)
226 int center = page / lineLength / 2;
227 clr_line(center - 2);
228 clr_line(center + 1);
229 displayCentered(msg1, center - 1);
230 displayCentered(msg2, center);
233 void displayMessageAndWaitForKey(char *msg)
235 displayTwoLineMessage(msg, pressAnyKey);
236 getch();
239 int displayMessageAndGetString(char *msg, char **last, char *p, int p_size)
241 int ret = TRUE;
243 displayOneLineMessage(msg);
244 ungetstr(*last);
245 echo();
246 getnstr(p, p_size - 1);
247 noecho();
248 if (*p == '\0') {
249 if (*last) strcpy(p, *last); else ret = FALSE;
250 } else {
251 FREE(*last);
252 *last = strdup(p);
254 return ret;
257 void ungetstr(char *s)
259 char *p;
260 if (s)
261 for (p = s + strlen(s) - 1; p >= s; p--) ungetch(*p);
264 int get_number(off_t *i)
266 char tmp[BLOCK_SEARCH_SIZE];
267 echo();
268 getnstr(tmp, BLOCK_SEARCH_SIZE - 1);
269 noecho();
270 int base = ((tmp[0] == '0' && tmp[1] == 'x') ? 16 : 10);
271 char *endptr;
272 unsigned long long val = strtoull(tmp, &endptr, base);
273 *i = val;
274 return (base == 16 && (size_t) endptr > ((size_t) tmp) + 2) ||
275 (base == 10 && endptr != tmp);