fix previously introduced bug
[rofl0r-hexedit0r.git] / display.c
blob65603a895177392f44f3411efeadbd8da2ab36af
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"
18 #include <errno.h>
20 int have_colors;
22 int move_cursor(INT delta)
24 return set_cursor(base + cursor + delta);
27 int set_cursor(INT loc)
29 if (loc < 0 && base % lineLength)
30 loc = 0;
32 if (!tryloc(loc))
33 return FALSE;
35 if (loc < base) {
36 if (loc - base % lineLength < 0)
37 set_base(0);
38 else if (!move_base(myfloor(loc - base % lineLength, lineLength) + base % lineLength - base))
39 return FALSE;
40 cursor = loc - base;
41 } else if (loc >= base + page) {
42 if (!move_base(myfloor(loc - base % lineLength, lineLength) + base % lineLength - page + lineLength - base))
43 return FALSE;
44 cursor = loc - base;
45 } else if (loc > base + nbBytes) {
46 return FALSE;
47 } else
48 cursor = loc - base;
50 if (mark_set)
51 updateMarked();
53 return TRUE;
56 int move_base(INT delta)
58 if (mode == bySector) {
59 if (delta > 0 && delta < page)
60 delta = page;
61 else if (delta < 0 && delta > -page)
62 delta = -page;
64 return set_base(base + delta);
67 int set_base(INT loc)
69 if (loc < 0) loc = 0;
71 if (!tryloc(loc)) return FALSE;
72 base = loc;
73 readFile();
75 if (mode != bySector && nbBytes < page - lineLength && base != 0) {
76 base -= myfloor(page - nbBytes - lineLength, lineLength);
77 if (base < 0) base = 0;
78 readFile();
81 if (cursor > nbBytes) cursor = nbBytes;
82 return TRUE;
86 int computeLineSize(void) { return computeCursorXPos(lineLength - 1, 0) + 1; }
87 int computeCursorXCurrentPos(void) { return computeCursorXPos(cursor, hexOrAscii); }
88 int computeCursorXPos(int cursor, int hexOrAscii)
90 int r = 11;
91 int x = cursor % lineLength;
92 int h = (hexOrAscii ? x : lineLength - 1);
94 r += normalSpaces * (h % blocSize) + (h / blocSize) * (normalSpaces * blocSize + 1) + (hexOrAscii && cursorOffset);
96 if (!hexOrAscii) r += x + normalSpaces + 1;
98 return r;
103 /*******************************************************************************/
104 /* Curses functions */
105 /*******************************************************************************/
106 void initCurses(void)
108 initscr();
109 have_colors = has_colors();
110 if (have_colors && colored) {
111 start_color();
112 use_default_colors();
113 init_pair(1, COLOR_RED, -1); /* null zeros */
114 init_pair(2, COLOR_GREEN, -1); /* control chars */
115 init_pair(3, COLOR_BLUE, -1); /* extended chars */
118 refresh();
119 raw();
120 noecho();
121 keypad(stdscr, TRUE);
123 if (mode == bySector) {
124 lineLength = modes[bySector].lineLength;
125 page = modes[bySector].page;
126 page = myfloor((LINES - 1) * lineLength, page);
127 blocSize = modes[bySector].blocSize;
128 if (computeLineSize() > COLS) DIE("%s: term is too small for sectored view (width)\n");
129 if (page == 0) DIE("%s: term is too small for sectored view (height)\n");
130 } else { /* mode == maximized */
131 if (LINES <= 4) DIE("%s: term is too small (height)\n");
133 blocSize = modes[maximized].blocSize;
134 for (lineLength = blocSize; computeLineSize() <= COLS; lineLength += blocSize);
135 lineLength -= blocSize;
136 if (lineLength == 0) DIE("%s: term is too small (width)\n");
138 page = lineLength * (LINES - 1);
140 colsUsed = computeLineSize();
141 buffer = malloc(page);
142 bufferAttr = malloc(page * sizeof(*bufferAttr));
145 void exitCurses(void)
147 close(fd);
148 clear();
149 refresh();
150 endwin();
153 void display(void)
155 int i;
157 for (i = 0; i < nbBytes; i += lineLength) {
158 move(i / lineLength, 0);
159 displayLine(i, nbBytes);
161 for (; i < page; i += lineLength) {
162 int j;
163 move(i / lineLength, 0);
164 for (j = 0; j < colsUsed; j++) printw(" "); /* cleanup the line */
165 move(i / lineLength, 0);
166 PRINTW(("%08lX", (int) (base + i)));
169 attrset(NORMAL);
170 move(LINES - 1, 0);
171 for (i = 0; i < colsUsed; i++) printw("-");
172 move(LINES - 1, 0);
173 if (isReadOnly) i = '%';
174 else if (edited) i = '*';
175 else i = '-';
176 printw("-%c%c %s --0x%llX", i, i, baseName, base + cursor);
177 if (MAX(fileSize, lastEditedLoc)) printw("/0x%llX", getfilesize());
178 if (mode == bySector) printw("--sector %d", (base + cursor) / SECTOR_SIZE);
180 move(cursor / lineLength, computeCursorXCurrentPos());
183 void displayLine(int offset, int max)
185 int i;
187 PRINTW(("%08lX ", (int) (base + offset)));
188 for (i = offset; i < offset + lineLength; i++) {
189 if (i > offset) MAXATTRPRINTW(bufferAttr[i] & MARKED, (((i - offset) % blocSize) ? " " : " "));
190 if (i < max) {
191 ATTRPRINTW(
192 (!(have_colors && colored) ? 0 :
193 buffer[i] == 0 ? COLOR_PAIR(1) :
194 buffer[i] < ' ' ? COLOR_PAIR(2) :
195 buffer[i] >= 127 ? COLOR_PAIR(3) : 0) |
196 bufferAttr[i], ("%02X", buffer[i]));
198 else PRINTW((" "));
200 PRINTW((" "));
201 for (i = offset; i < offset + lineLength; i++) {
202 if (i >= max) PRINTW((" "));
203 else if (buffer[i] >= ' ' && buffer[i] < 127) ATTRPRINTW(bufferAttr[i], ("%c", buffer[i]));
204 else ATTRPRINTW(bufferAttr[i], ("."));
208 void clr_line(int line) { move(line, 0); clrtoeol(); }
210 void displayCentered(char *msg, int line)
212 clr_line(line);
213 move(line, (COLS - strlen(msg)) / 2);
214 PRINTW(("%s", msg));
217 void displayOneLineMessage(char *msg)
219 int center = page / lineLength / 2;
220 clr_line(center - 1);
221 clr_line(center + 1);
222 displayCentered(msg, center);
225 void displayTwoLineMessage(char *msg1, char *msg2)
227 int center = page / lineLength / 2;
228 clr_line(center - 2);
229 clr_line(center + 1);
230 displayCentered(msg1, center - 1);
231 displayCentered(msg2, center);
234 void displayMessageAndWaitForKey(char *msg)
236 displayTwoLineMessage(msg, pressAnyKey);
237 getch();
240 int displayMessageAndGetString(char *msg, char **last, char *p, int p_size)
242 int ret = TRUE;
244 displayOneLineMessage(msg);
245 ungetstr(*last);
246 echo();
247 getnstr(p, p_size - 1);
248 noecho();
249 if (*p == '\0') {
250 if (*last) strcpy(p, *last); else ret = FALSE;
251 } else {
252 FREE(*last);
253 *last = strdup(p);
255 return ret;
258 void ungetstr(char *s)
260 char *p;
261 if (s)
262 for (p = s + strlen(s) - 1; p >= s; p--) ungetch(*p);
265 int get_number(INT *i)
267 char tmp[BLOCK_SEARCH_SIZE];
268 echo();
269 getnstr(tmp, BLOCK_SEARCH_SIZE - 1);
270 noecho();
271 int base = ((tmp[0] == '0' && tmp[1] == 'x') ? 16 : 10);
272 errno = 0;
273 unsigned long val = strtoul(tmp, NULL, base);
274 *i = val;
275 return (errno != EINVAL);