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 = <ext(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