remove unused file
[AROS.git] / workbench / tools / Edit / DiskIO.c
bloba8befac926097676e47f82093167a213e22f9966
1 /**************************************************************
2 **** diskio.c : procedures for accessing/writing on disk ****
3 **** Free software under GNU license, started on 25/2/2000 ****
4 **** © T.Pierron, C.Guillaume. ****
5 **************************************************************/
7 #include <intuition/intuition.h>
8 #include <libraries/asl.h>
9 #include <exec/memory.h>
10 #include <dos/dos.h>
11 #include "Project.h"
12 #include "DiskIO.h"
13 #include "Gui.h"
14 #include "Utility.h"
15 #include "ProtoTypes.h"
17 #define CATCOMP_NUMBERS /* Error msg use strings id */
18 #include "strings.h"
20 #define MEM_CHUNK 8192 /* To save file */
22 extern struct Library *AslBase;
24 extern struct Screen *Scr;
25 struct FileRequester *fr=NULL;
27 /* ASL load or save requester tags */
28 static IPTR tags[] = {
29 ASLFR_InitialLeftEdge, 0,
30 ASLFR_InitialTopEdge, 0,
31 ASLFR_InitialWidth, 320,
32 ASLFR_InitialHeight, 256,
33 ASLFR_Window, (IPTR) NULL,
34 ASLFR_Screen, (IPTR) NULL,
35 ASLFR_Flags1, 0,
36 ASLFR_SleepWindow, TRUE,
37 ASLFR_InitialDrawer, (IPTR) NULL,
38 ASLFR_InitialFile, (IPTR) NULL,
39 ASLFR_InitialPattern, (IPTR) NULL,
40 ASLFR_TitleText, (IPTR) NULL,
41 TAG_DONE
44 /*** Find the correctly spelled path ***/
45 BYTE get_full_path( STRPTR filename, STRPTR *dest )
47 STRPTR file = NULL, path;
48 BPTR lock;
49 WORD len;
51 len = sizeof(STR_MODIF) + 1;
52 lock = (BPTR) Lock(filename, SHARED_LOCK);
54 /* Can't get lock, surely because file does not exist */
55 if( lock == BNULL ) {
56 file = (STRPTR) FilePart(filename); len += strlen(file);
57 if(file != filename) {
58 char svg = *file; *file = 0;
59 lock = (BPTR) Lock(filename, SHARED_LOCK); *file = svg;
63 /* Be sure the locked object is of the desired type */
64 if(lock != BNULL)
66 struct FileInfoBlock *fib;
67 if((fib = (void *) AllocVec(sizeof(*fib), MEMF_PUBLIC)) && Examine(lock, fib))
69 /* That's particularly nasty, but prevent user of doing mistakes */
70 if(file == NULL ? fib->fib_EntryType > 0 : fib->fib_EntryType < 0)
71 /* Filename sucks, get a generic one */
72 UnLock(lock), lock = BNULL;
74 if( fib ) FreeVec( fib );
75 else { UnLock(lock); return ERR_NOMEM; }
76 /* User has given a directory as file to edit! */
77 if(file == NULL && lock == BNULL) return ERR_WRONG_TYPE;
80 /* The directory/file exists, Get its correctly spelled name */
81 for(len += 256; ;)
83 if( ( path = (STRPTR) AllocVec(len, MEMF_PUBLIC) ) ) {
84 /* If no directory provide, try to get the current wd */
85 if( lock ? NameFromLock(lock, path, len) :
86 GetCurrentDirName(path, len) )
88 /* At last if there was a file name, add it to the buffer */
89 if( file ) AddPart(path, file, len);
90 *dest = path;
91 break;
93 } else return ERR_NOMEM;
94 /* Fucking name! reallocate a longer buffer! */
95 FreeVec(path); len += 64;
97 if( lock ) UnLock(lock);
99 return 0;
102 /*** Extract path and file into 2 separate pointers (for ASL) ***/
103 void split_path(AskArgs *src, STRPTR *dir, STRPTR *file)
105 extern UBYTE BufTxt[256];
106 if( src->dir != NULL )
108 /* TODO cleanup */
109 UWORD Len = src->file - src->dir;
110 if(dir != NULL) {
111 if(Len >= sizeof(BufTxt)) Len = sizeof(BufTxt)-1;
112 CopyMem(src->dir, BufTxt, Len); BufTxt[Len] = '\0';
113 *dir = BufTxt;
114 } else Len = 0;
116 /* Copy file name */
117 *file = BufTxt+Len+1; Len = strlen( src->file );
118 CopyMem(src->file, *file, Len); (*file)[Len] = '\0';
120 else
122 *file = src->file;
123 if ( dir != NULL ) *dir = NULL;
127 /*** Encapsulated cleaning procedure of allocated things ***/
128 void free_diskio_alloc(void)
130 if(fr) FreeFileRequest(fr);
133 /*** Save width and height of an ASL requester ***/
134 void save_asl_dim(struct FileRequester *fr)
136 tags[5] = fr->fr_Width;
137 tags[7] = fr->fr_Height;
140 /*** Init the ASL tags table ***/
141 struct TagItem *init_tags(struct Window *wnd, ULONG flags)
143 /* Init LeftEdge */
144 tags[1] = wnd->LeftEdge + (wnd->Width-tags[5]) / 2;
145 /* TopEdge */
146 tags[3] = wnd->TopEdge + wnd->BorderTop;
147 /* Window, Screen, Flags */
148 tags[9] = (IPTR) wnd;
149 tags[11] = (IPTR) wnd->WScreen;
150 tags[13] = flags;
151 tags[21] = (IPTR) "#?";
152 return (struct TagItem *)tags;
155 /*** Popup a file requester to choose a save file ***/
156 STRPTR ask_save(struct Window *wnd, AskArgs *path, CONST_STRPTR title)
158 split_path(path, (STRPTR *)&tags[17], (STRPTR *)&tags[19]);
159 tags[23] = (IPTR)title;
161 /* If requester hasn't been allocated yet */
162 if(fr==NULL && !(fr = (void *)AllocAslRequest(ASL_FileRequest,NULL)))
163 ThrowError(Wnd, ErrMsg(ERR_NOASLREQ));
164 else
165 /* Display the file requester */
166 if(AslRequest(fr,init_tags(wnd, FRF_DOSAVEMODE | FRF_DOPATTERNS)))
168 STRPTR path;
169 save_asl_dim(fr);
170 /* User may choose strange path like "CPROG://docs/prog.c" **
171 ** get_full_path will search for the correct pathname */
172 if( ( path = CatPath(fr->fr_Drawer, fr->fr_File) ) )
174 STRPTR fullpath;
175 WORD err = get_full_path(path, &fullpath);
176 /* get_full_path, allocate a new buffer since size may vary */
177 FreeVec( path );
178 if( err == 0 ) return fullpath;
179 ThrowError(Wnd, ErrMsg(err));
180 } else
181 ThrowError(Wnd, ErrMsg(ERR_NOMEM));
183 return NULL;
186 /** Original FWrite has a too small buffer **/
187 static STRPTR buffer = NULL;
188 static ULONG usage = 0;
189 char myFWrite(BPTR file, CONST_STRPTR buf, ULONG size)
191 if(buffer == NULL && NULL == (buffer = (STRPTR) AllocVec(MEM_CHUNK, MEMF_PUBLIC)))
192 goto emergency;
194 if(size+usage > MEM_CHUNK) {
195 if( Write(file, buffer, usage) != usage ) return 0;
196 else usage = 0;
198 if(size > MEM_CHUNK)
199 emergency: return (char) (Write(file, buf, size) == size ? 1 : 0);
200 else
201 CopyMem(buf, buffer+usage, size), usage+=size;
202 return 1;
205 char myFClose( BPTR file )
207 char retcode = 1;
208 /* Flush buffer before closing */
209 if(buffer) {
210 /* Everything must be controlled */
211 if(usage > 0 && Write(file, buffer, usage) != usage)
212 retcode = 0;
213 FreeVec(buffer); buffer=NULL; usage=0;
215 Close(file);
216 return retcode;
219 /** Redirect functions **/
220 #ifdef FWrite
221 #undef FWrite
222 #endif
224 #define FWrite(x,y,z,t) myFWrite(x,y,z)
226 #ifdef FClose
227 #undef FClose
228 #endif
230 #define FClose(x) myFClose(x)
232 /*** Write the lines svg in the file `name', returns 1 if all's OK ***/
233 BYTE save_file(STRPTR name, LINE *svg, unsigned char eol, LONG protection)
235 STRPTR buf;
236 LONG i;
237 BYTE szeol = szEOL[eol];
238 LINE *ln; BPTR fh=BNULL;
239 BYTE retval = 0;
241 BusyWindow(Wnd);
243 if( ( fh = Open( name, MODE_OLDFILE) ) )
245 /* The file exists, Get protection flags */
246 struct FileInfoBlock *fib;
247 if( ( fib = (APTR) AllocDosObject( DOS_FIB, NULL ) ) )
249 if( ExamineFH(fh, fib) )
251 protection = fib->fib_Protection;
253 FreeDosObject( DOS_FIB, fib );
255 Close( fh );
258 fh = Open(name, MODE_NEWFILE);
260 if( fh )
262 for(ln=svg, buf=NULL, i=0; ln; ln=ln->next)
264 if(i == 0) buf = ln->stream;
265 /* An unmodified line (2nd cond. is for deleted lines) */
266 if(ln->max == 0 && ln->stream-buf == i) i+=ln->size+szeol;
268 else {
269 /* Flush preceding unmodified buffer */
270 i -= szeol;
271 if( i>=0 && (FWrite(fh, buf, i, 1) != 1 ||
272 FWrite(fh, chEOL+eol, szeol, 1) != 1 ) )
274 wrterr: ThrowDOSError(Wnd, name);
275 i=0; break;
278 /* Writes the modified line */
279 if( FWrite(fh, ln->stream, ln->size, 1) != 1 || (ln->next != NULL &&
280 FWrite(fh, chEOL+eol, szeol, 1) != 1 ) )
281 goto wrterr;
282 i=0;
285 /* Flush buffer */
286 if( i>szeol && FWrite(fh,buf,i-szeol,1)!=1 ) goto wrterr;
288 FClose( fh );
289 SetProtection(name, protection);
291 retval = 1;
293 } else if(IoErr() == ERROR_OBJECT_EXISTS)
294 ThrowError(Wnd, ErrMsg(ERR_WRONG_TYPE));
295 else
296 ThrowDOSError(Wnd, name);
298 WakeUp(Wnd);
299 return retval;
302 /*** Show a requester to choose a file to load ***/
303 STRPTR ask_load(struct Window *wnd, AskArgs *path, BYTE set_file, CONST_STRPTR title)
305 split_path(path, (STRPTR *)&tags[17], (STRPTR *)&tags[19]);
306 if(set_file == 0) tags[19] = 0;
307 tags[23] = (IPTR)title;
309 /* Alloc a file requester, if it hasn't been done yet */
310 if(fr==NULL && !(fr = (void *)AllocAslRequest(ASL_FileRequest,NULL)))
311 ThrowError(Wnd, ErrMsg(ERR_NOASLREQ));
312 else
313 /* Display the load requester */
314 if(AslRequest(fr, init_tags(wnd, (set_file ? FRF_DOPATTERNS : FRF_DOMULTISELECT|FRF_DOPATTERNS))))
316 STRPTR path;
317 save_asl_dim(fr);
318 /* This is actually a (StartUpArgs *) */
319 if( set_file == 0 ) return (STRPTR) &fr->fr_NumArgs;
321 if( ( path = CatPath(fr->fr_Drawer, fr->fr_File) ) )
323 STRPTR fullpath;
324 WORD err = get_full_path(path, &fullpath);
325 FreeVec( path );
326 if( err == 0 ) return fullpath;
327 ThrowError(Wnd, ErrMsg(err));
328 } else
329 ThrowError(Wnd, ErrMsg(ERR_NOMEM));
331 return NULL;
335 /*** Simple proc to read a file ***/
336 WORD read_file( LoadFileArgs *args, ULONG *len )
338 BPTR fh;
339 WORD err = RETURN_OK;
341 args->buffer = NULL;
342 args->lines = NULL;
343 args->protection = 0;
344 *len = 0;
346 if( ( fh = Open(args->filename, MODE_OLDFILE) ) )
348 /* First: Get file size */
349 struct FileInfoBlock *fib;
350 if( ( fib = (APTR) AllocDosObject( DOS_FIB, NULL ) ) )
352 if( ExamineFH(fh, fib) )
354 args->protection = fib->fib_Protection;
355 /* Then reads it in one large buffer */
356 if( (*len = fib->fib_Size) > 0 )
358 /* This is a critical call, with a high probability to fail ! */
359 if( ( args->buffer = (STRPTR) AllocVec(*len, MEMF_PUBLIC) ) )
361 if( Read(fh, args->buffer, *len) != *len )
362 err = ERR_LOADFILE;
364 else err = ERR_NOMEM;
366 /* This file is empty: we still need to allocate one line */
368 else err = ERR_LOADFILE;
369 FreeDosObject( DOS_FIB, fib );
371 else err = ERR_NOMEM;
373 Close( fh );
375 return err;
378 /*** load specified file from disk ***/
379 WORD load_file( LoadFileArgs *args )
381 ULONG len;
382 WORD err;
383 LINE * new;
385 BusyWindow(Wnd);
387 /* We have read the file in a buffer: create the lines */
388 if( RETURN_OK == (err = read_file( args, &len )) )
390 STRPTR p, q; char eol = '\n';
391 ULONG i;
393 args->eol = AMIGA_EOL;
394 /* Search in the very first line, the End Of Line type */
395 for(args->nblines=1, i=0, q=p=args->buffer;
396 i<len && *p!='\r' && *p!='\n'; p++, i++);
398 if( i < len && *p == '\r' )
399 args->eol = (p[1] == '\n' ? MSDOS_EOL : MACOS_EOL),
400 eol = '\r';
402 /* Build lines list */
403 if( ( args->lines = new = new_line(NULL) ) )
405 /* This loop is the most CPU consuming part */
406 for(; i<len; p++, i++)
407 if (*p == eol)
409 new->size = p-q;
410 /* *p = '\n'; Removed to preserve MS-DOS/Windows CRLF end-of-line chars */
411 new->stream = q;
412 args->nblines++;
413 if(args->eol == MSDOS_EOL && p[1]=='\n') p++,i++; q = p+1;
414 if(NULL == (new = new_line(new))) {
415 err = ERR_NOMEM; break;
418 new->size = p-q;
419 new->stream = q;
420 } else err = ERR_NOMEM;
422 /* If there was errors: cleanup all things */
423 if( err != 0 && args->lines ) trash_file(args->lines);
425 WakeUp(Wnd);
426 return err;