1 /* $Id: fileio.c,v 1.14 2001/04/15 16:35:45 amura Exp $ */
2 /*  OS dependent code used by Ng for WinCE.
3  *    Copyright (C) 1998 Eiichiro Ito
4  *  Modified for Ng for Win32
5  *    Copyright (C) 1999,2000 Toru Imai
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  ree Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * $Log: fileio.c,v $
24  * Revision 1.14  2001/04/15 16:35:45  amura
25  * patch for VC 6.0 from Katsuyoshi Ohara
26  *
27  * Revision 1.13  2001/03/02 08:48:32  amura
28  * now AUTOSAVE feature implemented almost all (except for WIN32
29  *
30  * Revision 1.12  2001/02/18 19:29:04  amura
31  * split dir.c to port depend/independ
32  *
33  * Revision 1.11  2001/01/17 18:34:53  amura
34  * now compile successfull on VC++ and BC++
35  *
36  * Revision 1.10  2001/01/05 14:07:08  amura
37  * first implementation of Hojo Kanji support
38  *
39  * Revision 1.9  2001/01/05 13:55:28  amura
40  * filename completion fixed
41  *
42  * Revision 1.8  2000/12/28 07:27:16  amura
43  * homedirctory support with filename complition
44  *
45  * Revision 1.7  2000/12/27 16:55:44  amura
46  * change d_makename() params for conservative reason, and bugfix in dires_()
47  *
48  * Revision 1.6  2000/12/14 18:10:48  amura
49  * filename length become flexible
50  *
51  * Revision 1.5  2000/11/16 14:21:28  amura
52  * merge Ng for win32 0.5
53  *
54  * Revision 1.4  2000/10/23 16:52:51  amura
55  * add GPL copyright to header
56  *
57  * Revision 1.3  2000/10/23 13:18:45  amura
58  * support Windoze line backup file
59  *
60  * Revision 1.2  2000/09/01 19:37:52  amura
61  * support KANJI filename on WIN32
62  *
63  * Revision 1.1.1.1  2000/06/27 01:47:59  amura
64  * import to CVS
65  *
66  */
67 
68 #include	<windows.h>
69 #include	<tchar.h>
70 #include	"config.h"
71 #include	"def.h"
72 #include	"tools.h"
73 #include "resource.h"
74 
75 #ifdef KANJI
76 void	bufetos( char *p, int len ) ;
77 int		bufstoe_c( char *p, int len ) ;
78 int		bufstoe( char *p, int len ) ;
79 #endif
80 void	kputc( char c, FILE* fp, int kfio ) ;
81 #if 0
82 char*	fftolower( char *name ) ;
83 #endif
84 int		bclear( BUFFER *bp ) ;
85 int		addline( BUFFER *bp, char *text ) ;
86 
87 #ifdef _WIN32_WCE
88 extern strnicmp(char *, char *, size_t);
89 #endif
90 
91 #ifndef HAVE_RINDEX
92 #define rindex(s,c)	strrchr(s,c)
93 #endif
94 
95 TCHAR	g_szPath[ MAX_PATH ] = TEXT("") ;
96 TCHAR	g_szCurDir[ MAX_PATH ] = TEXT("\\") ;
97 
98 #define	MALLOC_STEP	256
99 
100 int
fffiles(char * name,char ** buf)101 fffiles( char *name, char **buf )
102 {
103 	char	pathbuf[ NFILEN ], tmpnam[ NFILEN ] ;
104 	char	pathbufs[ NFILEN ], ff_namee[ NFILEN ] ;
105 	char	*cp, *dirpart, *nampart, *buffer ;
106 	int		n, len, size, dirpartlen, nampartlen, l ;
107 	HANDLE	hFind ;
108 	WIN32_FIND_DATA	find ;
109 	TCHAR	findPath[ MAX_PATH ], unicode[ MAX_PATH ] ;
110 #ifdef HOMEDIR
111 	char	*home;
112 	int	homelen;
113 #endif
114 
115 #ifndef _WIN32_WCE
116 	if (name[1] == ':' && name[2] == '\0') {
117 	  return -1;
118 	}
119 #endif
120 
121 #ifdef HOMEDIR
122 	if (name[0] == '~' && (name[1]=='/' || name[1]=='\\') &&
123 	    (home = getenv("HOME"))) {
124 		homelen = strlen(home)-1;
125 		strncpy(pathbuf, home, sizeof(pathbuf));
126 		pathbuf[NFILEN-1] = '\0';
127 		strncat(pathbuf, &name[1], sizeof(pathbuf)-strlen(pathbuf)-1);
128 	} else {
129 		home = NULL;
130 		homelen = 0;
131 		strncpy(pathbuf, name, sizeof(pathbuf));
132 		pathbuf[NFILEN-1] = '\0';
133     	}
134 #else
135 	strncpy(pathbuf, name, sizeof(pathbuf));
136 	pathbuf[NFILEN-1] = '\0';
137 #endif
138 	dirpart = NULL ;
139 	for ( cp = pathbuf ; *cp ; cp ++ ) {
140 		if ( *cp == '/' ) {
141 			*cp = '\\' ;
142 			dirpart = cp ;
143 		} else if ( *cp == '\\' ) {
144 			dirpart = cp ;
145 		} else if ( dirpart == NULL && *cp == ':' ) {
146 			dirpart = cp ;
147 		}
148 	}
149 	if ( dirpart ) {
150 		*++dirpart = '\0' ;
151 		dirpartlen = dirpart - pathbuf ;
152 	} else {
153 		strcpy( pathbuf, ".\\" ) ;	/* 90.05.30  by A.Shirahashi */
154 		dirpartlen = 0 ;
155 	}
156 #ifdef	HOMEDIR
157 	nampart = name + dirpartlen - homelen;
158 #else
159 	nampart = name + dirpartlen;
160 #endif
161 	nampartlen = strlen( nampart ) ;
162 
163 	buffer = malloc( MALLOC_STEP ) ;
164 	if ( buffer == NULL ) {
165 		return -1 ;
166 	}
167 	size = MALLOC_STEP ;
168 	len = 0 ;
169 	n = 0 ;
170 
171 	(VOID) strcat( pathbuf, "*.*" ) ;
172 	strcpy( pathbufs, pathbuf ) ;
173 #ifdef KANJI
174 	bufetos( pathbufs, strlen(pathbufs) + 1 ) ;
175 #endif
176 	/* Convert the search path to UNICODE and get absolute path */
177 	sjis2unicode( (LPBYTE) pathbufs, unicode, sizeof unicode ) ;
178 	rel2abs( findPath, g_szCurDir, unicode ) ;
179 	/* Find first file */
180 	hFind = FindFirstFile( findPath, &find ) ;
181 	if ( hFind == INVALID_HANDLE_VALUE ) {
182 		*buf = buffer ;
183 		buffer[0] = '\0' ;
184 		return 0 ;
185 	}
186 	do {
187 		if ( !lstrcmp( find.cFileName, TEXT(".") ) ) {
188 			continue ;
189 		} else if ( !lstrcmp( find.cFileName, TEXT("..") ) ) {
190 			continue ;
191 		}
192 		unicode2sjis( find.cFileName, (LPBYTE) ff_namee, sizeof ff_namee ) ;
193 #ifdef KANJI
194 		bufstoe( ff_namee, strlen(ff_namee) + 1 ) ;
195 #endif
196 		if ( strnicmp( nampart, ff_namee, nampartlen ) ) {
197 			continue ;		/* no-case-sensitive comparison */
198 		}
199 		strncpy( tmpnam, pathbuf, dirpartlen ) ;
200 		strcpy( tmpnam + dirpartlen, ff_namee ) ;
201 		if ( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
202 			strcat( tmpnam, "\\" ) ;
203 		}
204 		l = strlen(tmpnam) + 1 ;
205 		/* 90.05.30  by A.Shirahashi */
206 		if ( l > 5 && (stricmp( &tmpnam[l-5], ".OBJ" ) == 0 ||
207 						stricmp( &tmpnam[l-5], ".EXE" ) == 0 ||
208 						stricmp( &tmpnam[l-5], ".COM" ) == 0 ) ) {
209 			/* 90.05.30  by A.Shirahashi */
210 			continue ;
211 		}
212 		if ( l + len >= size ) {
213 			/* make room for double null */
214 			if ( ( buffer = realloc( buffer, size += MALLOC_STEP ) ) == NULL ) {
215 			        FindClose(hFind);
216 				return -1 ;
217 			}
218 		}
219 		/* 90.06.08  by A.Shirahashi: to */
220 		/* 00.12.28  by amura.. contributed by sahf */
221 #ifdef HOMEDIR
222 		if(home) {
223 			strcpy(buffer+len, "~");
224 			strcat(buffer+len, tmpnam+homelen+1);
225 			l -= homelen;
226 		} else
227 #endif
228 		strcpy( buffer + len, tmpnam ) ;
229 		len += l ;
230 		n ++ ;
231 	} while ( FindNextFile( hFind, &find ) ) ;
232 
233 	FindClose(hFind);
234 	*buf = buffer ;
235 	buffer[len] = '\0' ;
236 	return n ;
237 }
238 
239 char *
file_name_part(char * s)240 file_name_part( char *s )
241 {
242 	int		i ;
243 
244 	for (i = strlen (s); i > 0; i--) {
245 		if (s[i - 1] == '/' || s[i - 1] == '\\' || s[i - 1] == ':') {
246 			break ;
247 		}
248 	}
249 	return s + i ;
250 }
251 
252 #ifndef	NO_DIR
253 #include <tchar.h>
254 #include <direct.h>
255 #ifndef	__BORLANDC__
256 #define	chdir	_tchdir
257 #define	getcwd	_tgetcwd
258 #endif	/* __BORLANDC__ */
259 
260 extern char	*wdir;
261 extern char	*startdir;
262 static char	cwd[NFILEN];
263 
264 /*
265  * Initialize anything the directory management routines need
266  */
267 VOID
dirinit()268 dirinit()
269 {
270     char wdir2[NFILEN];
271 
272     if (!(wdir = getcwd(cwd, NFILEN-1)))
273 	panic("Can't get current directory!");
274     unicode2sjis(wdir, wdir2, sizeof(wdir2));
275     strcpy(wdir, wdir2);
276 #ifdef	KANJI
277     bufstoe(wdir, strlen(wdir)+1);
278 #endif
279 #ifndef	_WIN32_WCE
280     if (wdir[1]==':' && ISUPPER(wdir[0]))
281 	wdir[0] = TOLOWER(wdir[0]);
282 #endif	/* _WIN32_WCE */
283     if (startdir == NULL) {
284 	int len = strlen(cwd);
285 	startdir = malloc(len + 2);
286 	if (startdir == NULL) {
287 	    ewprintf("Cannot alloc %d bytes", len + 2);
288 	    return;
289 	}
290 	strcpy(startdir, cwd);
291     }
292 }
293 
294 /*
295    rchdir() makes some effects to change directory.  It will affect
296    system to set the actual current directory to the specified one.
297 
298    This routine is extracted from changedir(), which is currently do
299    some virtual chdir but previously do the actual one.
300 
301    Both bufc and wdir should have enough space to store file path, that
302    is, as long as NFILEN.
303 
304    By Tillanosoft, Mar 22, 1999
305  */
306 int
rchdir(newdir)307 rchdir(newdir)
308 char *newdir;
309 {
310     char dir[NFILEN], dir2[NFILEN];
311     int i;
312 
313     strcpy(dir2, newdir);
314 #ifdef	KANJI
315     bufetos(dir2, strlen(dir2)+1);
316 #endif
317     sjis2unicode(dir2, dir, sizeof(dir));
318     i = strlen(dir) - 1;
319     if (dir[i] == '\\')
320 	dir[i] = '\0';
321 #ifndef	_WIN32_WCE    /* WinCE has no drive */
322     if (dir[1] == ':' && dir[0] != wdir[0]) {
323 	int drive = newdir[0];
324 	/* 90.07.01  Change from TOUPPER() to TOLOWER() */
325 	/*                                 by S.Yoshida */
326 	if (ISUPPER(drive))
327 	    drive = TOLOWER(drive);
328 	/* 90.07.01  Change from 'A' to 'a' by S.Yoshida */
329 	drive = drive - 'a' + 1;
330 	_chdrive(drive);
331     }
332     if (dir[1] == ':') {
333 	if (dir[2]=='\0') {
334 	    dirinit();
335 	    return 0;
336 	} else if (chdir(dir+2) == -1)
337 	    return -1;
338     } else
339 #endif
340     if (chdir(dir) == -1)
341 	return -1;
342     dirinit();
343     return 0;
344 }
345 #endif
346 
347 /*
348  * The string "fn" is a file name.
349  * Perform any required appending of directory name or case adjustments.
350  * If NO_DIR is not defined, the same file should be refered to even if the
351  * working directory changes.
352  */
353 
354 char *
adjustname(char * fn)355 adjustname( char *fn )
356 {
357 	HANDLE hFind;
358 	TCHAR findPath[MAX_PATH];
359 	WIN32_FIND_DATA find;
360 	char		*cp ;
361 	static char	fnb[ NFILEN ] ;
362 
363 	cp = fnb ;
364 #ifndef _WIN32_WCE
365 	if (fn[1] == ':') {
366 	  *cp++ = *fn++;
367 	  *cp++ = *fn++;
368 	}
369 #endif
370 #ifdef HOMEDIR
371 #ifndef _WIN32_WCE
372 	else
373 #endif
374 	if (fn[0]=='~' && (fn[1]=='/' || fn[1]=='\\')) {
375 		strcpy(fnb, getenv("HOME"));
376 		while (*cp) {
377     			if (*cp == '/')
378     				*cp = '\\';
379     			cp++;
380     		}
381 		fn++;
382 	}
383 #endif
384 	switch( *fn ) {
385 	case '/':
386 		*fn = '\\' ;
387 	case '\\':
388 		*cp++ = *fn++ ;
389 		break ;
390 #ifndef _WIN32_WCE
391         case '\0':
392 		break;
393 #endif
394 	default:
395 #ifndef	NO_DIR	/* 91.01.17  NODIR -> NO_DIR. by S.Yoshida */
396 #if 0 /* something incomprehensive thing is done here */
397 		extern	char	*wdir ;
398 
399 		if ( cp == fnb || fnb[0] == wdir[0] ) {
400 			(VOID) strcpy( fnb, wdir ) ;
401 			cp = fnb + strlen( fnb ) ;
402 		} else
403 #endif
404 		{			/* Different drive. */
405 			unicode2sjis( g_szCurDir, (LPBYTE) fnb, NFILEN - 1 ) ;
406 #if 0 /* to prevent making lower case */
407 			/* 90.07.01  Add fftolower() by S.Yoshida */
408 			if ( !fftolower( fnb ) ) {
409 				cp = fnb ;
410 			} else {
411 				cp = fnb + strlen( fnb ) ;
412 			}
413 #else /* not 0 */
414 			cp = fnb ? fnb + strlen(fnb) : fnb;
415 #endif
416 		}
417 		break ;
418 #else
419 		return fn ;				/* punt */
420 #endif
421 	}
422 	if ( cp != fnb && cp[-1] != '\\' ) {
423 		*cp++ = '\\' ;
424 	}
425 	while ( *fn ) {
426 		switch ( *fn ) {
427 		case '.':
428 			switch ( fn[1] ) {
429 			case '\0':
430 				*--cp = '\0' ;
431 				return fnb ;
432 			case '/':
433 			case '\\':
434 				fn += 2 ;
435 				continue ;
436 			case '.':
437 				if ( fn[2]=='\\' || fn[2] == '/' || fn[2] == '\0' ) {
438 					--cp ;
439 					while ( cp > fnb && *--cp != '\\' ) {
440 					}
441 					++cp ;
442 					if ( fn[2] == '\0' ) {
443 						*cp = '\0' ;
444 						goto finalcheck;
445 					}
446 					fn += 3 ;
447 					continue ;
448 				}
449 				break ;
450 			default:
451 				break ;
452 			}
453 			break ;
454 		case '/':
455 		case '\\':
456 			fn ++ ;
457 			continue ;
458 		default:
459 			break ;
460 		}
461 		while ( *fn && (*cp++ = *fn++) != '\\' ) {
462 #if 0
463 			/* 90.06.05  by S.Yoshida */
464 			/* 90.06.08  by A.Shirahashi, convert to lower case */
465 			if ( ISUPPER( cp[-1] ) ) {
466 				cp[-1] = TOLOWER( cp[-1] ) ;
467 			}
468 #endif
469 			if ( cp[-1] == '/' ) {
470 				cp[-1] = '\\' ;
471 				break ;
472 			}
473 		}
474 	}
475       finalcheck:
476 	if ( cp[-1] == '\\' ) {
477 #ifndef _WIN32_WCE
478 	        if (cp == &fnb[3] && fnb[1] == ':') {
479 		  /* It's OK */
480 		} else
481 #endif
482 		if ( cp != &fnb[1] ) {
483 			--cp ;
484 		}
485 	}
486 	*cp = '\0' ;
487 
488 	/* Do final confirmation for the case of the file name.  This
489 	   is very essential because Win32 file system tells the case
490 	   of file names for writing but does not tell for reading.
491 	   The purpose here is to confirm the actual case of the
492 	   existing file name by reading the folder using
493 	   FindFirstFile(). */
494 
495 	sjis2unicode(fnb, findPath, MAX_PATH * sizeof(TCHAR));
496 	hFind = FindFirstFile(findPath, &find);
497 	if (hFind != INVALID_HANDLE_VALUE) {
498 	  for (cp = fnb + strlen(fnb) ; fnb < cp ;) {
499 	    if (*--cp == '\\') {
500 	      cp++;
501 	      break;
502 	    }
503 	  }
504 	  unicode2sjis(find.cFileName, cp, NFILEN - (cp - fnb));
505 	  FindClose(hFind);
506 	}
507 	return fnb ;
508 }
509 
510 /*
511  * Open a file for reading.
512  */
513 int
ffropen(char * fn)514 ffropen( char *fn )
515 {
516 	CHAR	fns[ NFILEN ] ;
517 	TCHAR	unicode[ MAX_PATH ] ;
518 
519 	strcpy( fns, fn ) ;
520 #ifdef KANJI
521 	bufetos( fns, strlen(fns) + 1 ) ;
522 #endif
523 	unicode[0] = 0 ;
524 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
525 	rel2abs( g_szPath, g_szCurDir, unicode ) ;
526 	if ( !Fopen( g_szPath, TEXT("r") ) ) {
527 		return FIOFNF ;
528 	}
529 	return FIOSUC ;
530 }
531 
532 /*
533  * Open a file for writing.
534  * Return TRUE if all is well, and
535  * FALSE on error (cannot create).
536  */
537 int
ffwopen(char * fn)538 ffwopen( char *fn )
539 {
540 	CHAR	fns[ NFILEN ] ;
541 	TCHAR	unicode[ MAX_PATH ] ;
542 
543 	strcpy( fns, fn ) ;
544 #ifdef KANJI
545 	bufetos( fns, strlen(fns) + 1 ) ;
546 #endif
547 	unicode[0] = 0 ;
548 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
549 	rel2abs( g_szPath, g_szCurDir, unicode ) ;
550 	if ( !Fopen( g_szPath, TEXT("w") ) ) {
551 		ewprintf( "Cannot open file for writing" ) ;
552 		return FIOERR ;
553 	}
554 	return FIOSUC ;
555 }
556 
557 /*
558  * Close a file.
559  * Should look at the status.
560  */
561 int
ffclose()562 ffclose()
563 {
564 	Fclose() ;
565 	return FIOSUC ;
566 }
567 
568 /*
569  * Write a buffer to the already
570  * opened file. bp points to the
571  * buffer. Return the status.
572  * Check only at the newline and
573  * end of buffer.
574  */
575 int
ffputbuf(BUFFER * bp)576 ffputbuf( BUFFER *bp )
577 {
578 	char	*cp ;
579 	char	*cpend ;
580 	LINE	*lp ;
581 	LINE	*lpend ;
582 #ifdef KANJI
583 	int		kfio ;
584 #endif
585 
586 	lpend = bp->b_linep ;
587 #ifdef KANJI
588 	kfio  = bp->b_kfio ;
589 #endif
590 	lp = lforw(lpend) ;
591 	do {
592 		cp = &ltext(lp)[0] ;		/* begining of line	*/
593 		cpend = &cp[llength(lp)] ;	/* end of line		*/
594 		while ( cp != cpend ) {
595 #ifdef KANJI
596 			kputc( *cp, NULL, kfio ) ;
597 #else
598 			putc(*cp, NULL);
599 #endif
600 			cp ++ ;		/* putc may evalualte arguments more than once */
601 		}
602 #ifdef KANJI
603 		if ( kfio == JIS ) {
604 			kfselectcode(NULL, FALSE) ;
605 		}
606 #endif
607 		lp = lforw( lp ) ;
608 		if ( lp == lpend ) {
609 			break ;		/* no implied newline on last line */
610 		}
611 		putc( '\n', NULL) ;
612 	} while( !Ferror() ) ;
613 	if ( Ferror() ) {
614 		ewprintf( "Write I/O error" ) ;
615 		return FIOERR ;
616 	}
617 	return FIOSUC ;
618 }
619 
620 /*
621  * Read a line from a file, and store the bytes
622  * in the supplied buffer. Stop on end of file or end of
623  * line.  When FIOEOF is returned, there is a valid line
624  * of data without the normally implied \n.
625  */
626 int
ffgetline(char * buf,int nbuf,int * nbytes)627 ffgetline( char *buf, int nbuf, int *nbytes )
628 {
629 	int		c ;
630 	int		i ;
631 
632 	i = 0 ;
633 	while ( ( c = Fgetc() ) != -1 && c != '\n' ) {
634 		buf[ i++ ] = c ;
635 		if ( i >= nbuf ) {
636 			return FIOLONG ;
637 		}
638 	}
639 	if ( c == -1  && Ferror() != FALSE ) {
640 		ewprintf( "File read error" ) ;
641 		return FIOERR ;
642 	}
643 	*nbytes = i ;
644 	return c == -1 ? FIOEOF : FIOSUC ;
645 }
646 
647 #ifdef	READONLY
648 /*
649  * Check whether file is read-only of a file fn.
650  */
651 int
fchkreadonly(char * fn)652 fchkreadonly( char *fn )
653 {
654 	DWORD	attr ;
655 	char	fns[ NFILEN ] ;
656 	TCHAR	szPath[ MAX_PATH ], unicode[ MAX_PATH ] ;
657 
658 	strcpy( fns, fn ) ;
659 #ifdef KANJI
660 	bufetos( fns, strlen( fns ) + 1 ) ;
661 #endif
662 	/* Generate absolute path based on the current directory */
663 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
664 	rel2abs( szPath, g_szCurDir, unicode ) ;
665 	attr = GetFileAttributes( szPath ) ;
666 	if ( attr == 0xFFFFFFFF ) {
667 		return FALSE ;
668 	}
669 	return attr & FILE_ATTRIBUTE_READONLY ;
670 }
671 #endif	/* READONLY */
672 
673 #ifndef	NO_STARTUP
674 
675 /*
676  * Find a startup file for the user and return its name. As a service
677  * to other pieces of code that may want to find a startup file (like
678  * the terminal driver in particular), accepts a suffix to be appended
679  * to the startup file name.
680  */
681 /*ARGSUSED*/
682 char *
683 #ifdef	ADDOPT
startupfile(ngrcfile,suffix)684 startupfile(ngrcfile, suffix)
685 char* ngrcfile;
686 #else
687 startupfile(suffix)
688 #endif
689 char* suffix;
690 {
691   static BYTE sjis[MAX_PATH];
692   TCHAR	unicode[MAX_PATH];
693   DWORD foo = sizeof(unicode);
694 
695 #ifdef ADDOPT
696   if (ngrcfile) {
697     lstrcpy(unicode, ngrcfile);
698     if (GetFileAttributes(unicode) != 0xFFFFFFFF) {
699 #ifdef	_WIN32_WCE
700 	  unicode2sjis(unicode, sjis, sizeof sjis);
701 #else
702 	  strncpy(sjis, unicode,  sizeof sjis);
703 	  sjis[(sizeof sjis)-1] = '\0';
704 #endif
705 #ifdef KANJI
706 	  bufstoe(sjis, strlen(sjis)+1);
707 #endif
708       return (char*)sjis;
709     }
710   }
711 #endif
712   if (RegQueryString(HKEY_CURRENT_USER, NGREGKEY, NGSTARTUPFILEVAL,
713 		     unicode, &foo) != ERROR_SUCCESS) {
714     if (GetFileAttributes(unicode) == 0xFFFFFFFF) {
715       lstrcpy(unicode, NGDEFAULTINIFILE);
716       if (GetFileAttributes(unicode) == 0xFFFFFFFF) {
717 	lstrcpy(unicode, TEXT("\\Storage Card") NGDEFAULTINIFILE);
718 	if (GetFileAttributes(unicode) == 0xFFFFFFFF) {
719 	  return NULL;
720 	}
721       }
722     }
723   }
724   unicode2sjis(unicode, sjis, sizeof sjis);
725 #ifdef	KANJI
726   bufstoe(sjis, strlen(sjis)+1);
727 #endif
728   return (char*)sjis;
729 }
730 
731 #endif	/* NO_STARTUP */
732 
733 #ifndef NO_DIRED
734 #include "kbd.h"
735 
736 int		mkfileline( LPSTR *_line, WIN32_FIND_DATA *info ) ;
737 
738 int
unlink(const char * fn)739 unlink( const char *fn )
740 {
741 	char	fns[ NFILEN ] ;
742 	TCHAR	unicode[ MAX_PATH ], szPath[ MAX_PATH ] ;
743 
744 	strcpy( fns, fn ) ;
745 #ifdef KANJI
746 	bufetos( fns, strlen( fns ) + 1 ) ;
747 #endif
748 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
749 	rel2abs( szPath, g_szCurDir, unicode ) ;
750 
751 	return DeleteFile( szPath ) ? 0 : -1 ;
752 }
753 
754 int
rmdir(const char * fn)755 rmdir( const char *fn )
756 {
757 	char	fns[ NFILEN ] ;
758 	TCHAR	unicode[ MAX_PATH ], szPath[ MAX_PATH ] ;
759 
760 	strcpy( fns, fn ) ;
761 #ifdef KANJI
762 	bufetos( fns, strlen( fns ) + 1 ) ;
763 #endif
764 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
765 	rel2abs( szPath, g_szCurDir, unicode ) ;
766 	return RemoveDirectory( szPath ) ? 0 : -1 ;
767 }
768 
769 int
rename(const char * oldfn,const char * newfn)770 rename( const char *oldfn, const char *newfn )
771 {
772 	static	char	oldfns[ NFILEN ], newfns[ NFILEN ] ;
773 	static	TCHAR	unicode[ MAX_PATH ], szOldPath[ MAX_PATH ], szNewPath[ MAX_PATH ] ;
774 
775 	strcpy( oldfns, oldfn ) ;
776 #ifdef KANJI
777 	bufetos( oldfns, strlen( oldfns ) + 1 ) ;
778 #endif
779 	sjis2unicode( (LPBYTE) oldfns, unicode, sizeof unicode ) ;
780 	rel2abs( szOldPath, g_szCurDir, unicode ) ;
781 
782 	strcpy( newfns, newfn ) ;
783 #ifdef KANJI
784 	bufetos( newfns, strlen( newfns ) + 1 ) ;
785 #endif
786 	sjis2unicode( (LPBYTE) newfns, unicode, sizeof unicode ) ;
787 	rel2abs( szNewPath, g_szCurDir, unicode ) ;
788 
789 	return MoveFile( szOldPath, szNewPath ) ? 0 : -1 ;
790 }
791 
792 int
copy(char * oldfn,char * newfn)793 copy( char *oldfn, char *newfn )
794 {
795 	static	char	oldfns[ NFILEN ], newfns[ NFILEN ] ;
796 	static	TCHAR	unicode[ MAX_PATH ], szOldPath[ MAX_PATH ], szNewPath[ MAX_PATH ] ;
797 
798 	strcpy( oldfns, oldfn ) ;
799 #ifdef KANJI
800 	bufetos( oldfns, strlen( oldfns ) + 1 ) ;
801 #endif
802 	sjis2unicode( (LPBYTE) oldfns, unicode, sizeof unicode ) ;
803 	rel2abs( szOldPath, g_szCurDir, unicode ) ;
804 
805 	strcpy( newfns, newfn ) ;
806 #ifdef KANJI
807 	bufetos( newfns, strlen( newfns ) + 1 ) ;
808 #endif
809 	sjis2unicode( (LPBYTE) newfns, unicode, sizeof unicode ) ;
810 	rel2abs( szNewPath, g_szCurDir, unicode ) ;
811 
812 	return CopyFile( szOldPath, szNewPath, FALSE ) ? 0 : -1 ;
813 }
814 
815 BUFFER *
dired_(char * dirname)816 dired_( char *dirname )
817 {
818 	BUFFER	*bp ;
819 	BUFFER	*findbuffer() ;
820 	char	**files, **getfilelist() ;
821 	int		numfiles ;
822 	int		i ;
823 
824 	if ( ( dirname = adjustname( dirname ) ) == NULL ) {
825 		ewprintf( "Bad directory name" ) ;
826 		return NULL ;
827 	}
828 	if ( dirname[ strlen( dirname ) - 1 ] != '\\' ) {
829 		(VOID) strcat( dirname, "\\" ) ;
830 	}
831 	if ( ( bp = findbuffer( dirname ) ) == NULL ) {
832 		ewprintf( "Could not create buffer" ) ;
833 		return NULL ;
834 	}
835 	if ( bclear( bp ) != TRUE ) {
836 		return FALSE ;
837 	}
838 	if ( ( files = getfilelist( &numfiles, dirname ) ) == NULL ) {
839 		ewprintf( "Could not get directory info" ) ;
840 		return NULL ;
841 	}
842 	for ( i = 0 ; i < numfiles ; i ++ ) {
843 		(VOID) addline( bp, files[i] ) ;
844 		free( files[i] ) ;
845 	}
846 	free( files ) ;
847 	bp->b_dotp = lforw( bp->b_linep ) ;		/* go to first line */
848 	if (bp->b_fname != NULL) free(bp->b_fname);
849 	if ((bp->b_fname=malloc(strlen(dirname)+1)) != NULL)
850 		(VOID) strcpy(bp->b_fname, dirname);
851 #ifdef EXTD_DIR
852 	if(bp->b_cwd != NULL) free(bp->b_cwd);
853 	bp->b_cwd = NULL;
854 #endif
855 	if ( ( bp->b_modes[0] = name_mode( "dired" ) ) == NULL ) {
856 		bp->b_modes[0] = &map_table[0] ;
857 		ewprintf( "Could not find mode dired" ) ;
858 		return NULL ;
859 	}
860 	bp->b_nmodes = 0 ;
861 	return bp ;
862 }
863 
864 int
d_makename(LINE * lp,char * fn,int buflen)865 d_makename( LINE *lp, char *fn, int buflen)
866 {
867 	char	*cp ;
868 	int len;
869 
870 	if ( llength( lp ) <= 41 ) {
871 		return ABORT ;
872 	}
873 	len = strlen(curbp->b_fname) + llength(lp) - 41;
874 	if (buflen <= len) return ABORT;
875 	cp = fn;
876 	strcpy(cp, curbp->b_fname);
877 	cp += strlen(cp);
878 	bcopy(lp->l_text + 41, cp, llength(lp) - 41);
879 	fn[len] = '\0';
880 	return lgetc(lp, 2) == 'd';
881 }
882 
883 static int __cdecl
884 #ifdef __BORLANDC__
filelinecmp(const void * x,const void * y)885 filelinecmp(const void *x, const void *y)
886 #else
887 filelinecmp(const char **x, const char **y)
888 #endif
889 {
890 	register unsigned char	*xx, *yy;
891 
892 #ifdef __BORLANDC__
893 	xx = (unsigned char*)&(*(char **)x)[41];
894 	yy = (unsigned char*)&(*(char **)y)[41];
895 #else
896 	xx = (unsigned char*)&(*x)[41];
897 	yy = (unsigned char*)&(*y)[41];
898 #endif
899 
900 	if (*xx != *yy) {		/* for "." ".." directories */
901 		if (*xx == '.') return -1;
902 		if (*yy == '.') return 1;
903 	  	return(*xx - *yy);
904 	}
905 
906 	if (*xx) {
907 		for (xx++, yy++; *xx && *xx == *yy; xx++, yy++) {}
908 	}
909 	return(*xx - *yy);
910 }
911 
912 char **
getfilelist(int * numfiles,char * dirname)913 getfilelist( int *numfiles, char *dirname )
914 {
915   char **files;
916   int maxfiles, n;
917   char filename[NFILEN];
918   char filenames[NFILEN];
919   HANDLE hFind = INVALID_HANDLE_VALUE;
920   TCHAR	unicode[MAX_PATH], findPath[MAX_PATH];
921   WIN32_FIND_DATA find;
922 
923   n = 0; /* store n to *numfiles later */
924   if (strlen(dirname) + 4 > NFILEN) {
925     *numfiles = n;
926     return NULL;
927   }
928   (VOID)strcpy(filename, dirname);
929   (VOID)strcat(filename, "*.*");
930 
931   maxfiles = 50; /* Magic number here.  Should be eliminated */
932   files = (char **)malloc(maxfiles * sizeof(char *));
933   if (files) {
934     memset(files, 0, maxfiles * sizeof(char *));
935 
936     strcpy(filenames, filename);
937 #ifdef KANJI
938     bufetos(filenames, strlen(filenames) + 1);
939 #endif
940     /* Convert the search path to UNICODE and get absolute path */
941     sjis2unicode((LPBYTE)filenames, unicode, sizeof(unicode));
942     rel2abs(findPath, g_szCurDir, unicode);
943     /* Add ".." except for root dir */
944     if (*dirname && strcmp(dirname, "\\")) {
945       if (!mkfileline(files + n, NULL)) {
946 	goto failed;
947       }
948       n++;
949     }
950     /* Find first file */
951     hFind = FindFirstFile(findPath, &find);
952     if (hFind != INVALID_HANDLE_VALUE) {
953       do {
954 	if (!lstrcmp(find.cFileName, TEXT("."))) {
955 	  continue; /* ignore '.' */
956 	} else if (!lstrcmp(find.cFileName, TEXT(".."))) {
957 	  continue; /* ignore '..' */
958 	}
959 	if (n >= maxfiles) {
960 	  files = (char **)realloc(files, sizeof(char *) * (maxfiles + 20));
961 	  if (files == NULL) {
962 	    goto failed;
963 	  }
964 	  maxfiles += 20;
965 	}
966 	if (mkfileline(files + n, &find)) {
967 	  n++;
968 	}
969       } while (FindNextFile(hFind, &find));
970 
971       FindClose(hFind);
972       qsort(files, n, sizeof(char *), filelinecmp);
973       *numfiles = n;
974       return files;
975     }
976     else {
977       DWORD err = GetLastError();
978 
979       if (err == ERROR_NO_MORE_FILES || err == ERROR_FILE_NOT_FOUND) {
980 	*numfiles = n; /* 'n' must be 1 */
981 	return files;
982       }
983     }
984   }
985  failed:
986   if (hFind != INVALID_HANDLE_VALUE) {
987     FindClose(hFind);
988   }
989   if (files) {
990     char **pp, **epp;
991     for (pp = files, epp = pp + n ; pp < epp ; pp++) {
992       free(*pp);
993     }
994     free(files);
995   }
996   *numfiles = 0;
997   return NULL;
998 }
999 
1000 int
mkfileline(LPSTR * lptr,WIN32_FIND_DATA * info)1001 mkfileline( LPSTR *lptr, WIN32_FIND_DATA *info )
1002 {
1003 	SYSTEMTIME	st ;
1004 	FILETIME	lft ;
1005 	int			len ;
1006 	BYTE		sjis[ MAX_PATH ] ;
1007 	TCHAR		unicode[ MAX_PATH ], *line = unicode ;
1008 
1009 	line[0] = line[1] = TEXT(' ') ;
1010 	line[2] = !info || (info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TEXT('d') : TEXT('-') ;
1011 	line[3] = TEXT('r') ;
1012 	line[4] = !info || (info->dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? TEXT('-') : TEXT('w') ;
1013 	line[5] = TEXT('-') ;
1014 	line[6] = info && (info->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? TEXT('a') : TEXT('-') ;
1015 	wsprintf( &line[7], TEXT("%13d"), info ? info->nFileSizeLow : 0 ) ;
1016 	if ( info
1017 	  && FileTimeToLocalFileTime( &info->ftLastWriteTime, &lft )
1018 	  && FileTimeToSystemTime( &lft, &st ) ) {
1019 		wsprintf( &line[20], TEXT("  %4d-%02d-%02d  %02d:%02d  "),
1020 				  st.wYear, st.wMonth, st.wDay,
1021 				  st.wHour, st.wMinute ) ;
1022 	} else {
1023 		lstrcpy( &line[20], TEXT("                     ") ) ;
1024 	}
1025 	lstrcpy( &line[41], info ? info->cFileName : TEXT("..") ) ;
1026 	unicode2sjis( unicode, sjis, sizeof sjis ) ;
1027 #ifdef KANJI
1028 	len = bufstoe_c( sjis, strlen( sjis ) + 1 ) ;
1029 #else
1030 	len = strlen(sjis) + 1;
1031 #endif
1032 	(*lptr) = (LPSTR) malloc( len * sizeof (CHAR) ) ;
1033 	if ( !*lptr ) {
1034 		return FALSE ;
1035 	}
1036 	strcpy( *lptr, sjis ) ;
1037 #ifdef KANJI
1038 	(VOID) bufstoe( &(*lptr)[41], strlen( &(*lptr)[41] ) + 1 ) ;
1039 #endif
1040 #if 0
1041 	(VOID) fftolower( &(*lptr)[41] ) ;
1042 #endif
1043 	return TRUE ;
1044 }
1045 
1046 /*
1047  * Check whether file "dn" is directory.
1048  */
1049 int
ffisdir(char * dn)1050 ffisdir( char *dn )
1051 {
1052 	DWORD	attr ;
1053 	char	dns[ NFILEN ] ;
1054 	TCHAR	szPath[ MAX_PATH ], szUnicode[ MAX_PATH ] ;
1055 
1056 	strcpy( dns, dn ) ;
1057 #ifdef KANJI
1058 	bufetos( dns, strlen( dns ) + 1 ) ;
1059 #endif
1060 	sjis2unicode( (LPBYTE) dns, szUnicode, sizeof szUnicode ) ;
1061 	/* Generate absolute path based on the current directory */
1062 	rel2abs( szPath, g_szCurDir, szUnicode ) ;
1063 	attr = GetFileAttributes( szPath ) ;
1064 	if ( attr == 0xFFFFFFFF ) {
1065 #if 0
1066 		DWORD err = GetLastError();
1067 #endif
1068 		return FALSE ;
1069 	}
1070 	return attr & FILE_ATTRIBUTE_DIRECTORY ;
1071 }
1072 #endif
1073 
1074 #if 0
1075 /* 90.07.01  Add function to convert strings into lower case by S.Yoshida */
1076 char *
1077 fftolower( char *name )
1078 {
1079 	char	*p ;
1080 
1081 	if ( (p = name) != NULL ) {
1082 		while ( *p != '\0' ) {
1083 			if ( ISUPPER( *p ) ) {
1084 				*p = TOLOWER( *p ) ;
1085 			}
1086 			p ++ ;
1087 		}
1088 	}
1089 	return name ;
1090 }
1091 #endif
1092 
1093 int
chdir(const char * dir)1094 chdir( const char *dir )
1095 {
1096 	DWORD	attr ;
1097 	TCHAR	unicode[ MAX_PATH ], szPath[ MAX_PATH ] ;
1098 
1099 	sjis2unicode( (LPBYTE) dir, unicode, sizeof unicode ) ;
1100 	rel2abs( szPath, g_szCurDir, unicode ) ;
1101 	attr = GetFileAttributes( szPath ) ;
1102 	if ( attr == 0xFFFFFFFF || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) {
1103 		return -1 ;
1104 	}
1105 	lstrcpy( g_szCurDir, szPath ) ;
1106 	return 0 ;
1107 }
1108 
1109 #ifndef	NO_BACKUP
1110 /*
1111  * Get file mode of a file fn.
1112  */
1113 int
fgetfilemode(char * fn)1114 fgetfilemode( char *fn )
1115 {
1116 	DWORD	attr ;
1117 	char	fns[ NFILEN ] ;
1118 	TCHAR	unicode[ MAX_PATH ], szPath[ MAX_PATH ] ;
1119 
1120 	strcpy( fns, fn ) ;
1121 #ifdef KANJI
1122 	bufetos( fns, strlen( fns ) + 1 ) ;
1123 #endif
1124 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
1125 	rel2abs( szPath, g_szCurDir, unicode ) ;
1126 	attr = GetFileAttributes( szPath ) ;
1127 	if ( attr == 0xFFFFFFFF ) {
1128 		return -1 ;
1129 	}
1130 	return (int) attr ;
1131 }
1132 
1133 /*
1134  * Set file mode of a file fn to the specified mode.
1135  */
1136 VOID
fsetfilemode(char * fn,int mode)1137 fsetfilemode( char *fn, int mode )
1138 {
1139 	char	fns[ NFILEN ] ;
1140 	TCHAR	unicode[ MAX_PATH ], szPath[ MAX_PATH ] ;
1141 
1142 	strcpy( fns, fn ) ;
1143 #ifdef KANJI
1144 	bufetos( fns, strlen( fns ) + 1 ) ;
1145 #endif
1146 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
1147 	rel2abs( szPath, g_szCurDir, unicode ) ;
1148 	SetFileAttributes( szPath, (DWORD) mode ) ;
1149 }
1150 
1151 /*
1152  * Rename the file "fname" into a backup
1153  * copy. On Unix the backup has the same name as the
1154  * original file, with a "~" on the end; this seems to
1155  * be newest of the new-speak. The error handling is
1156  * all in "file.c".
1157  */
1158 int
fbackupfile(char * fn)1159 fbackupfile( char *fn )
1160 {
1161 	int	len;
1162 	char	*nname ;
1163 	VOID	strmfe() ;	/* 90.07.26  Add by N.Kamei */
1164 	char	fns[ NFILEN ] ;
1165 	char	nnames[ NFILEN ] ;
1166 	TCHAR unicode[NFILEN];
1167 	TCHAR	szFns[ MAX_PATH ] ;
1168 	TCHAR	szNNames[ MAX_PATH ] ;
1169 
1170 #ifdef EMACS_BACKUP_STYLE
1171 	len = strlen(fn) + 1 + 1;
1172 #else
1173 	len = strlen(fn) + 4 + 1;
1174 #endif
1175 	if ( ( nname = alloca(len) ) == NULL ) {
1176 		ewprintf( "Can't get %d bytes", len) ;
1177 		return ABORT ;
1178 	}
1179 	(VOID) strcpy(nname, fn);
1180 #ifdef EMACS_BACKUP_STYLE
1181 	(VOID) strcat(nname, "~");
1182 #else
1183 	(VOID) strcat(nname, ".bak");
1184 #endif
1185 	strcpy( nnames, nname ) ;
1186 	strcpy( fns, fn ) ;
1187 #ifdef KANJI
1188 	bufetos( nnames, strlen( nnames ) + 1 ) ;
1189 	bufetos( fns, strlen( fns ) + 1 ) ;
1190 #endif
1191 	sjis2unicode( (LPBYTE) nnames, unicode, sizeof unicode ) ;
1192 	rel2abs( szNNames, g_szCurDir, unicode ) ;
1193 	sjis2unicode( (LPBYTE) fns, unicode, sizeof unicode ) ;
1194 	rel2abs( szFns, g_szCurDir, unicode ) ;
1195 	DeleteFile( szNNames ) ;
1196 	if ( MoveFile( szFns, szNNames ) < 0 )
1197 		return FALSE ;
1198 	return TRUE ;
1199 }
1200 #endif	/* NO_BACKUP */
1201 
1202 #ifdef	AUTOSAVE
1203 VOID
autosave_name(buff,name,buflen)1204 autosave_name(buff, name, buflen)
1205 char* buff;
1206 char* name;
1207 {
1208     strcpy(buff, name);
1209     if (strlen(name)) {
1210 	char *fn = rindex(name, '/');
1211 	if (fn == NULL)
1212 	    fn = rindex(name, '\\');
1213 	if (fn == NULL)
1214 	    fn = rindex(name, ':');
1215 	if (fn == NULL){
1216 	    fn = buff;
1217 	} else {
1218 	    fn++;
1219 	}
1220 	strcpy(&buff[strlen(buff)-strlen(fn)], "#");
1221 	strcat(buff, fn);
1222 	strcat(buff, "#");
1223     }
1224 }
1225 #endif	/* AUTOSAVE */
1226