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