1 /* DOSIO.C - file I/O and alloc subroutines for MSDOS - BVI
2 *
3 * 1996-02-28 V 1.0.0
4 * 1998-04-12 V 1.0.1
5 * 1999-01-14 V 1.1.0
6 * 1999-04-27 V 1.1.1
7 * 1999-07-02 V 1.2.0 beta
8 * 1999-09-01 V 1.2.0 final
9 * 2000-05-02 V 1.3.0 alpha
10 *
11 * NOTE: Edit this file with tabstop=4 !
12 *
13 * Copyright 1996-2002 by Gerhard Buergmann
14 * Gerhard.Buergmann@puon.at
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2, or (at your option) any
19 * later version.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * See file COPYING for information on distribution conditions.
27 */
28
29 #include <conio.h>
30 #include <alloc.h>
31 #include <fcntl.h>
32 #include <bios.h>
33 #include <io.h>
34 #include <mem.h>
35 #include "bvi.h"
36 #include "set.h"
37
38 char *terminal = "ansi";
39
40 extern maxy;
41 struct WINDOW scr;
42
43 int stdscr = 0;
44
45 int COLS = 80;
46 int LINES = 25;
47 int ECHO = TRUE;
48 int NODEL = FALSE;
49
50 static struct stat buf;
51 int filemode;
52
53 int inch(void);
54
55 void
attrset(int attr)56 attrset(int attr)
57 {
58 switch(attr) {
59 case A_NORMAL: textcolor(P(P_CO) & 0x07);
60 textbackground((P(P_CO) & 0xf0) >> 4);
61 break;
62 case A_BOLD: textcolor((P(P_CO) & 0x07) | 0x08);
63 textbackground((P(P_CO) & 0xf0) >> 4);
64 break;
65 case A_REVERSE: textcolor((P(P_CO) & 0xf0) >> 4);
66 textbackground(P(P_CO) & 0x0f);
67 break;
68 case A_BLINK: textcolor((P(P_CO) & 0xf0) >> 4);
69 textbackground(P(P_CO) & 0x0f);
70 break;
71 }
72 }
73
74
75 int
getch()76 getch()
77 {
78 int x;
79
80 if (NODEL) if (!kbhit()) return(ERR);
81 x = bioskey(0);
82 if ((x & 0xff) == 0) return(x);
83 else {
84 x &= 0xff;
85 if (ECHO) putch(x);
86 return(x); }
87 }
88
89
90 void
delch()91 delch()
92 {
93 int x, y;
94
95 x = wherex(); y = wherey();
96 movetext(x + 1, y, COLS - x, y, x, y);
97 gotoxy(COLS, y);
98 putch(' ');
99 gotoxy(x, y);
100 }
101
102
103 void
insch(int c)104 insch(int c)
105 {
106 char line[80];
107 int x, y;
108
109 x = wherex(); y = wherey();
110 gettext(x, y, COLS - x, y, line);
111 puttext(x + 1, y, COLS - x + 1, y, line);
112 putch(c);
113 }
114
115
116 int
inch()117 inch()
118 {
119 return peek(0xb800, (wherex() - 1) + (wherey() - 1) * COLS);
120 }
121
122 int
mvinch(int y,int x)123 mvinch(int y, int x)
124 {
125 gotoxy(x + 1, y + 1);
126 return inch();
127 }
128
129
130 /*********** Save the patched file ********************/
131 int
save(char * fname,PTR start,PTR end,int flags)132 save(char *fname, PTR start, PTR end, int flags)
133 {
134 int fd;
135 char string[255];
136 char *newstr;
137 off_t written;
138 off_t filesize;
139 unsigned n, to_write;
140
141 if (!fname) {
142 emsg("No file|No current filename");
143 return 0;
144 }
145 if (stat(fname, &buf) == -1) {
146 newstr = "[New file] ";
147 } else {
148 if (S_ISDIR(buf.st_mode)) {
149 sprintf(string, "\"%s\" Is a directory", fname);
150 msg(string);
151 return 0;
152 }
153 newstr = "";
154 }
155
156 if (filemode == PARTIAL) flags = O_RDWR;
157 if ((fd = open(fname, flags, 0666)) < 0) {
158 sysemsg(fname);
159 return 0;
160 }
161 if (filemode == PARTIAL) {
162 if (block_read) {
163 filesize = block_read;
164 sprintf(string, "\"%s\" range %lu-%lu", fname,
165 (unsigned long)block_begin,
166 (unsigned long)(block_begin - 1 + filesize));
167 if (lseek(fd, block_begin, SEEK_SET) < 0) {
168 sysemsg(fname);
169 return 0;
170 }
171 } else {
172 msg("Null range");
173 return 0;
174 }
175 } else {
176 filesize = end - start + 1L;
177 sprintf(string, "\"%s\" %s%lu@bytes", fname, newstr, (long)filesize);
178 }
179
180 written = 0;
181 do {
182 to_write = (filesize - written) > 0xfffe ? 0xfffe : (filesize - written);
183 if ((n = write(fd, start + written, to_write)) == 0xffff) {
184 sysemsg(fname);
185 close(fd);
186 return(0L);
187 }
188 written += (off_t)n;
189 } while (written < filesize);
190 close(fd);
191 edits = 0;
192 msg(string);
193 return 1;
194 }
195
196
197 off_t
load(char * fname)198 load(char *fname)
199 {
200 int fd = -1;
201 char string[MAXCMD];
202 unsigned chunk, n;
203
204 buf.st_size = filesize = 0L;
205 if (fname != NULL) {
206 if (stat(fname, &buf) == -1) {
207 filemode = NEW;
208 } else if (S_ISDIR(buf.st_mode)) {
209 filemode = DIRECTORY;
210 } else if (S_ISREG(buf.st_mode)) {
211 if ((fd = open(fname, O_RDONLY|O_BINARY)) > 0) {
212 filemode = REGULAR;
213 if (access(fname, 2)) {
214 P(P_RO) = TRUE;
215 params[P_RO].flags |= P_CHANGED;
216 }
217 } else {
218 sysemsg(fname);
219 filemode = ERROR;
220 }
221 }
222 } else {
223 filemode = NEW;
224 }
225 if (mem != NULL) farfree(mem);
226 if (block_flag) {
227 memsize = block_size + 1000;
228 } else if (filemode == REGULAR) {
229 memsize = buf.st_size + 100;
230 } else {
231 memsize = 1000;
232 }
233
234 if (farcoreleft() < memsize) {
235 move(maxy, 0);
236 endwin();
237 printf("\n\nOut of memory\n");
238 exit(0);
239 }
240 mem = (char huge *)farmalloc(memsize);
241
242 clear_marks();
243 if (block_flag && (filemode == REGULAR)) {
244 if (lseek(fd, block_begin, SEEK_SET) < 0) {
245 sysemsg(fname);
246 filemode = ERROR;
247 } else {
248 chunk = block_size > 0xfffe ? 0xfffe : block_size;
249 do {
250 if ((n = read(fd, mem + filesize, chunk)) == 0xffff) {
251 sysemsg(fname);
252 filemode = ERROR;
253 break;
254 }
255 filesize += (off_t)n;
256 } while (filesize < buf.st_size);
257 if ((filesize == 0) {
258 sprintf(string, "\"%s\" No such range: %lu-%lu", fname,
259 (unsigned long)block_begin, (unsigned long)(block_end));
260 } else {
261 sprintf(string, "\"%s\" range %lu-%lu", fname,
262 (unsigned long)block_begin,
263 (unsigned long)(block_begin + filesize - 1));
264 }
265 filemode = PARTIAL;
266 block_read = filesize;
267 msg(string);
268 P(P_OF) = block_begin;
269 params[P_OF].flags |= P_CHANGED;
270 }
271 } else if (filemode == REGULAR) {
272 chunk = buf.st_size > 0xfffe ? 0xfffe : buf.st_size;
273 do {
274 if ((n = read(fd, mem + filesize, chunk)) == 0xffff) {
275 sysemsg(fname);
276 filemode = ERROR;
277 break;
278 }
279 filesize += (off_t)n;
280 } while (filesize < buf.st_size);
281 }
282 if (fd > 0) close(fd);
283 if (filemode != REGULAR) {
284 filesize = 0L;
285 }
286 if (fname != NULL) {
287 switch (filemode) {
288 case NEW:
289 sprintf(string, "\"%s\" [New File]", fname);
290 break;
291 case REGULAR:
292 sprintf(string, "\"%s\" %s%lu bytes", fname,
293 P(P_RO) ? "[Read only] " : "", (long)filesize);
294 break;
295 case DIRECTORY:
296 sprintf(string, "\"%s\" Directory", fname);
297 break;
298 }
299 if (filemode != ERROR) msg(string);
300 }
301 pagepos = mem;
302 maxpos = (PTR)(mem + filesize);
303 loc = HEX;
304 x = AnzAdd; y = 0;
305 repaint();
306 return(filesize);
307 }
308
309
310 int
311 addfile(char *fname)
312 {
313 int fd;
314 off_t oldsize;
315 unsigned chunk, n;
316
317 if (stat(fname, &buf)) {
318 sysemsg(fname);
319 return 1;
320 }
321 if ((fd = open(fname, O_RDONLY)) == -1) {
322 sysemsg(fname);
323 return 1;
324 }
325 oldsize = filesize;
326 if (enlarge(buf.st_size)) return 1;
327 chunk = buf.st_size > 0xfffe ? 0xfffe : buf.st_size;
328 do {
329 if ((n = read(fd, mem + filesize, chunk)) == 0xffff) {
330 sysemsg(fname);
331 filemode = ERROR;
332 return 1;
333 }
334 filesize += (off_t)n;
335 } while (filesize < buf.st_size);
336 maxpos = mem + filesize;
337 close(fd);
338 setpage(mem + oldsize);
339 return 0;
340 }
341
342
343 void
344 bvi_init(char *dir)
345 {
346 char *poi;
347 char *initstr;
348 char rcpath[255];
349
350 shell = getenv("COMSPEC");
351 if (shell == NULL || *shell == '\0')
352 shell = "COMMAND.COM";
353
354 strcpy(rcpath, dir);
355 poi = strrchr(rcpath, '\\');
356 *poi = '\0';
357 strcat(rcpath, "\\BVI.RC");
358
359 if ((initstr = getenv("BVIINIT")) != NULL) {
360 docmdline(initstr);
361 }
362 read_rc("BVI.RC");
363 read_rc(rcpath);
364 }
365
366
367 int
368 enlarge(off_t add)
369 {
370 PTR newmem;
371 off_t savecur, savepag, savemax, saveundo;
372
373 savecur = curpos - mem;
374 savepag = pagepos - mem;
375 savemax = maxpos - mem;
376 saveundo = undo_start - mem;
377
378 newmem = (PTR)farrealloc(mem, memsize + add);
379 if (newmem == NULL) {
380 emsg("Out of memory");
381 return 1;
382 }
383 mem = newmem;
384 memsize += add;
385 curpos = mem + savecur;
386 pagepos = mem + savepag;
387 maxpos = mem + savemax;
388 undo_start = mem + saveundo;
389 current = curpos + 1;
390 return 0;
391 }
392
393
394 void
395 do_shell()
396 {
397 system("");
398 }
399
400
401 off_t
402 alloc_buf(off_t n, char **buffer)
403 {
404 if ((*buffer = (char *)farrealloc(*buffer, n)) == NULL) {
405 emsg("No buffer space available");
406 return 0L;
407 }
408 return n;
409 }
410
411
412 void
413 d_memmove(PTR dest, PTR src, off_t n)
414 {
415 unsigned len;
416 long chunk;
417 PTR source;
418 PTR destin;
419
420 chunk = n;
421 if (dest < src) {
422 /* copy forward */
423 source = src;
424 destin = dest;
425 while (chunk > 0L) {
426 len = chunk > 0x7ffe ? 0x7ffe : chunk;
427 movmem(source, destin, len);
428 chunk -= len;
429 source += len;
430 destin += len;
431 }
432 } else {
433 /* copy backward */
434 source = src + n;
435 destin = dest + n;
436 while (chunk > 0L) {
437 len = chunk > 0x7ffe ? 0x7ffe : chunk;
438 chunk -= len;
439 source -= len;
440 destin -= len;
441 movmem(source, destin, len);
442 }
443 }
444 }
445
446 void
447 d_memcpy(PTR dest, PTR src, off_t n)
448 {
449 unsigned len;
450 long chunk;
451 PTR source;
452 PTR destin;
453
454 source = src;
455 destin = dest;
456 chunk = n;
457 while (chunk > 0L) {
458 len = chunk > 0x7ffe ? 0x7ffe : chunk;
459 movmem(source, destin, len);
460 chunk -= len;
461 source += len;
462 destin += len;
463 }
464 }
465