finally the biggest changes together with makefile. hardcoded flag removed.
[AROS-Contrib.git] / dopus / Program / buffers.c
blob61eae80cba0476495a83c6c1111e8b42901eb035
1 /*
3 Directory Opus 4
4 Original GPL release version 4.12
5 Copyright 1993-2000 Jonathan Potter
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
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.
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.
21 All users of Directory Opus 4 (including versions distributed
22 under the GPL) are entitled to upgrade to the latest version of
23 Directory Opus version 5 at a reduced price. Please see
24 http://www.gpsoft.com.au for more information.
26 The release of Directory Opus 4 under the GPL in NO WAY affects
27 the existing commercial status of Directory Opus 5.
31 #include "dopus.h"
33 /* Allocate or free directory buffers as necessary to achieve desired
34 buffer count in each window */
36 void allocdirbuffers(newnum)
37 int newnum;
39 int win,a,num;
40 struct DirectoryWindow *dir,*next;
42 for (win=0;win<2;win++) {
43 if (data_buffer_count[win]>newnum) {
44 dir=dopus_firstwin[win];
45 for (a=0;a<newnum;a++) dir=dir->next;
46 dir->last->next=dopus_firstwin[win];
47 dopus_firstwin[win]->last=dir->last;
48 num=data_buffer_count[win];
49 for (a=newnum;a<num;a++) {
50 next=dir->next;
51 freedir(dir,-1);
52 if (dopus_curwin[win]==dir) dopus_curwin[win]=dopus_firstwin[win];
53 FreeMem(dir,sizeof(struct DirectoryWindow));
54 if ((--data_buffer_count[win])<1) break;
55 dir=next;
58 else if (data_buffer_count[win]<newnum) {
59 dir=dopus_firstwin[win];
60 for (a=0;a<data_buffer_count[win]-1;a++) dir=dir->next;
61 for (a=data_buffer_count[win];a<newnum;a++) {
62 if (next=AllocMem(sizeof(struct DirectoryWindow),MEMF_CLEAR)) {
63 if (!dir) {
64 dopus_firstwin[win]=next;
65 dopus_curwin[win]=next;
66 dir=next;
68 dir->next=next;
69 next->last=dir;
70 next->next=dopus_firstwin[win];
71 dopus_firstwin[win]->last=next;
72 next->number=a;
73 next->hlen=145;
74 ++data_buffer_count[win];
75 dir=next;
82 /* Searches both buffer lists for a given directory, and displays it in
83 the active window if found (copying it over if necessary) */
85 int bringinbuffer(dirbuf,win,read)
86 char *dirbuf;
87 int win,read;
89 int a,otherwin;
90 struct DirectoryWindow *dir;
92 if (status_iconified || !dirbuf) return(0);
93 checkcurrentbuffer(win);
94 if (!(findbuffer(dirbuf,win,0,0))) {
95 otherwin=1-data_active_window;
96 dir=dopus_firstwin[otherwin];
97 for (a=0;a<data_buffer_count[otherwin];a++,dir=dir->next) {
98 if ((Stricmp(dirbuf,dir->directory))==0) {
99 incrementbuf(data_active_window,1,0);
100 copydirwin(dir,dopus_curwin[data_active_window],data_active_window);
101 check_old_buffer(data_active_window);
102 return(1);
105 if (read) {
106 strcpy(str_pathbuffer[data_active_window],dirbuf);
107 startgetdir(data_active_window,SGDFLAGS_CANMOVEEMPTY);
109 else return(0);
111 return(1);
114 /* Searches forward from the current buffer to find an empty one, or one
115 with the same name (it looks first for one with the same name).
116 If a buffer is not found, it uses the current buffer */
118 void findemptybuffer(win)
119 int win;
121 struct DirectoryWindow *dir=dopus_curwin[win],*oldestdir;
122 int a,ok=0;
123 char fullbuf[256];
125 if (dir->flags & DWF_ARCHIVE) return;
126 //D(bug("findemptybuffer()\n"));
127 expand_path(str_pathbuffer[win],fullbuf);
128 checkdir(str_pathbuffer[win],NULL);
129 checkdir(fullbuf,NULL);
131 for (a=0;a<data_buffer_count[win];a++) {
132 if (Stricmp(dir->directory,str_pathbuffer[win])==0 ||
133 Stricmp(dir->directory,fullbuf)==0) {
134 ok=1;
135 break;
137 dir=dir->next;
139 if (!ok) {
140 oldestdir=dir=dopus_curwin[win];
141 for (a=0;a<data_buffer_count[win];a++) {
142 if (!dir->directory[0])
144 oldestdir=dir;
145 break;
147 if (CompareDates(&oldestdir->dirstamp,&dir->dirstamp)<0) oldestdir=dir;
148 dir=dir->next;
150 dir=oldestdir;
152 dopus_curwin[win]=dir;
155 /* Sets up and reads a new directory */
157 void startgetdir(win,flags)
158 int win,flags;
160 checkcurrentbuffer(win);
161 //D(bug("startgetdir %s\ncurrent: %s\n",str_pathbuffer[win],dopus_curwin[win]->directory));
162 if (!(config->dirflags&DIRFLAGS_CHECKBUFS && (flags&SGDFLAGS_CANCHECKBUFS)) ||
163 !(findbuffer(str_pathbuffer[win],win,1,0))) {
164 if ((config->dirflags&DIRFLAGS_FINDEMPTY) && (flags&SGDFLAGS_CANMOVEEMPTY))
165 findemptybuffer(win);
166 if (str_pathbuffer[win][0]==0) expand_path("",str_pathbuffer[win]);
167 checkdir(str_pathbuffer[win],&path_strgadget[win]);
168 //D(bug("path: %s\n",str_pathbuffer[win]));
169 strcpy(dopus_curwin[win]->directory,str_pathbuffer[win]);
170 getdir(dopus_curwin[win],win,(flags&SGDFLAGS_REREADINGOLD));
172 seename(win);
173 refreshwindow(win,0);
176 /* Moves forward or backward a buffer and refreshes display */
178 void incrementbuf(win,dir,show)
179 int win,dir,show;
181 advancebuf(win,dir);
182 strcpy(str_pathbuffer[win],dopus_curwin[win]->directory);
183 checkdir(str_pathbuffer[win],&path_strgadget[win]);
184 checksize(win);
185 check_old_buffer(win);
186 if (show) {
187 seename(win);
188 refreshwindow(win,1);
189 doselinfo(win);
191 startnotify(win);
194 /* Copies the contents of one window to another */
196 void copydirwin(sourcewin,destwin,dest)
197 struct DirectoryWindow *sourcewin,*destwin;
198 int dest;
200 struct Directory *copy;
202 if (status_iconified) return;
203 busy();
204 freedir(destwin,dest);
205 copy=sourcewin->firstentry;
206 strcpy(destwin->realdevice,sourcewin->realdevice);
207 while (copy) {
208 if (!(addfile(destwin,dest,copy->name,copy->size,copy->type,&copy->date,
209 copy->comment,copy->protection,copy->subtype,FALSE,copy->dispstr,NULL,
210 copy->owner_id,copy->group_id))) break;
211 copy=copy->next;
213 strcpy(str_pathbuffer[dest],sourcewin->directory);
214 strcpy(destwin->directory,sourcewin->directory);
215 strcpy(destwin->diskname,sourcewin->diskname);
216 destwin->hlen=sourcewin->hlen;
217 destwin->flags=sourcewin->flags;
218 copy_datestamp(&sourcewin->dirstamp,&destwin->dirstamp);
219 refreshwindow(dest,1);
220 checkdir(str_pathbuffer[dest],&path_strgadget[dest]);
221 checksize(dest);
222 last_selected_entry=NULL;
223 okay();
224 unbusy();
227 /* Swaps the contents of the two windows */
229 void swapdirwin()
231 int tmp;
232 struct DirectoryWindow tempwin;
234 if (status_iconified) return;
236 CopyMem((char *)dopus_curwin[0],(char *)&tempwin,sizeof(struct DirectoryWindow));
237 tempwin.next=dopus_curwin[1]->next; tempwin.number=dopus_curwin[1]->number;
238 tempwin.last=dopus_curwin[1]->last;
239 dopus_curwin[1]->next=dopus_curwin[0]->next; dopus_curwin[1]->number=dopus_curwin[0]->number;
240 dopus_curwin[1]->last=dopus_curwin[0]->last;
241 CopyMem((char *)dopus_curwin[1],(char *)dopus_curwin[0],sizeof(struct DirectoryWindow));
242 CopyMem((char *)&tempwin,(char *)dopus_curwin[1],sizeof(struct DirectoryWindow));
244 for (tmp=0;tmp<2;tmp++) {
245 strcpy(str_pathbuffer[tmp],dopus_curwin[tmp]->directory);
246 refreshwindow(tmp,1);
247 checkdir(str_pathbuffer[tmp],&path_strgadget[tmp]);
248 checksize(tmp);
250 okay();
253 /* Moves forwards or backwards a directory */
255 void advancebuf(win,dir)
256 int win,dir;
258 int a;
260 endnotify(win);
261 if (!checkcurrentbuffer(win)) {
262 if (dir>0) {
263 for (a=0;a<dir;a++) dopus_curwin[win]=dopus_curwin[win]->next;
265 else {
266 for (a=dir;a<0;a++) dopus_curwin[win]=dopus_curwin[win]->last;
271 /* Clears the contents of all unshown buffers */
273 void clearbuffers()
275 int a,win;
276 struct DirectoryWindow *dir;
278 busy();
279 for (win=0;win<2;win++) {
280 dir=dopus_firstwin[win];
281 for (a=0;a<data_buffer_count[win];a++) {
282 if (dopus_curwin[win]!=dir) {
283 freedir(dir,-1);
284 dir->directory[0]=0;
286 dir=dir->next;
289 unbusy();
290 dostatustext(globstring[STR_BUFFERS_CLEARED]);
293 /* Searches backwards for a named buffer and moves to it if found */
295 struct DirectoryWindow *findbuffer(dirbuf,win,canchecklocks,onlyreturn)
296 char *dirbuf;
297 int win,canchecklocks,onlyreturn;
299 struct FileInfoBlock __aligned fblock;
300 int a,founddir=0,ret=0,try,checklocks=0;
301 struct DirectoryWindow *dir;
302 BPTR lock=0,testlock;
303 char tempbuf[300];
305 //D(bug("findbuffer()\n"));
306 if (status_iconified) return(NULL);
307 dir=dopus_curwin[win];
308 if (dir->flags & DWF_ARCHIVE) return NULL;
309 main_proc->pr_WindowPtr=(APTR)-1;
311 strcpy(tempbuf,dirbuf);
313 if (config->dirflags&DIRFLAGS_EXPANDPATHS) {
314 canchecklocks=0;
315 expand_path(dirbuf,tempbuf);
318 TackOn(tempbuf,NULL,300);
320 for (try=0;try<2;try++) {
321 if (checklocks && !(lock=Lock(tempbuf,ACCESS_READ))) break;
323 for (a=0;a<data_buffer_count[win];a++,dir=dir->last) {
324 if (dir->directory[0]) {
325 if (checklocks &&
326 (testlock=Lock(dir->directory,ACCESS_READ))) {
327 if (CompareLock(lock,testlock)==LOCK_SAME) founddir=1;
328 UnLock(testlock);
329 if (!founddir) continue;
331 if (founddir || (Stricmp(tempbuf,dir->directory))==0) {
332 if (!(lockandexamine(tempbuf,&fblock)) ||
333 (CompareDates(&fblock.fib_Date,&dir->dirstamp)!=0)) continue;
334 if (!onlyreturn) go_to_buffer(win,dir);
335 ret=1;
336 break;
340 if (ret) break;
341 if (canchecklocks) checklocks=1;
342 else break;
344 UnLock(lock);
345 if (config->errorflags&ERROR_ENABLE_DOS) main_proc->pr_WindowPtr=(APTR)Window;
346 return((ret)?dir:NULL);
349 /* Checks all buffers for a pathname and changes it to the new
350 pathname if found */
352 void renamebuffers(old,new)
353 char *old,*new;
355 int a,win;
356 struct DirectoryWindow *dir;
358 for (win=0;win<2;win++) {
359 dir=dopus_firstwin[win];
360 for (a=0;a<data_buffer_count[win];a++) {
361 if (replacepart(dir->directory,old,new) && dopus_curwin[win]==dir) {
362 strcpy(str_pathbuffer[win],dir->directory);
363 checkdir(str_pathbuffer[win],&path_strgadget[win]);
365 dir=dir->next;
370 int replacepart(string,old,new)
371 char *string,*old,*new;
373 int oldlen,stringlen;
374 char tempbuf[256];
376 oldlen=strlen(old);
377 if (Strnicmp(string,old,oldlen)) return(0);
378 if ((stringlen=strlen(string))>oldlen) {
379 stringlen-=oldlen;
380 strncpy(tempbuf,&string[oldlen],stringlen);
381 tempbuf[stringlen]=0;
383 else stringlen=0;
384 strcpy(string,new);
385 if (stringlen>0) StrConcat(string,tempbuf,256);
386 return(1);
389 /* Generates a list of all available buffers in a window */
391 void dolistbuffers(destwin)
392 int destwin;
394 int a,b,c,win;
395 struct DateStamp ds;
396 struct DirectoryWindow *dir;
397 char name[2];
399 if (status_iconified) return;
400 makespecialdir(destwin,globstring[STR_BUFFER_LIST_TITLE]);
402 busy(); b=0/*scrdata_dispwin_nchars[destwin]*/; name[0]=0;
403 DateStamp(&ds);
404 for (win=0;win<2;win++) {
405 dir=dopus_firstwin[win];
406 for (a=0;a<data_buffer_count[win];a++) {
407 if (dir->directory[0]) {
408 addfile(dopus_curwin[destwin],destwin,name,0,
409 ENTRY_CUSTOM,&ds,dir->directory,0,
410 CUSTOMENTRY_BUFFERLIST,FALSE,dir->directory,NULL,0,0);
411 if ((c=strlen(dir->directory))>b) b=c;
412 //D(bug("dolistbuffers: %ld - (%s)\n",c,dir->directory));
414 dir=dir->next;
417 b*=scrdata_font_xsize;
418 b+=2;
419 if (b<scrdata_dispwin_nchars[destwin]) b=scrdata_dispwin_nchars[destwin];
420 dopus_curwin[destwin]->hlen=b;
421 D(bug("dolistbuffers: %ld, %ld\n",dopus_curwin[destwin]->hlen,scrdata_dispwin_nchars[destwin]));
422 refreshwindow(destwin,3);
423 unbusy();
424 okay();
427 /* Check if buffer is a special buffer, and return to normal if so */
429 int checkcurrentbuffer(win)
430 int win;
432 if (dopus_curwin[win]==dopus_specialwin[win]) {
433 dopus_curwin[win]=dopus_oldwin[win];
434 return(1);
436 return(0);
439 /* Send message to custom entry handler */
441 void userentrymessage(dir,entry,type)
442 struct DirectoryWindow *dir;
443 struct Directory *entry;
444 int type;
446 struct RexxMsg *msg,*reply;
447 struct MsgPort *port;
448 int fail=0;
450 /* If no customhandler installed or rexx library is not there, return */
451 if (!dir->custhandler[0] || !RexxSysBase) return;
453 /* Attempt to create the message packet */
454 if (!(msg=CreateRexxMsg(general_port,NULL,str_arexx_portname))) fail=1;
455 else {
456 /* Set message type (and argument count of 4) */
457 msg->rm_Action=RXFUNC|4;
459 /* Fill out argument pointers.
461 Arg0 = operation type
462 Arg1 = entry number
463 Arg2 = entry text
464 Arg3 = userdata */
466 msg->rm_Args[0]=(STRPTR)type;
467 msg->rm_Args[1]=entry->name;
468 msg->rm_Args[2]=entry->comment;
469 msg->rm_Args[3]=(STRPTR)entry->protection;
471 /* Fill in the message correctly.
472 Arguments are integer/string/string/integer
473 1 0 0 1 = 9 */
475 if (!(FillRexxMsg(msg,4,9))) fail=1;
478 /* If we failed to create the message properly, release it and return */
479 if (fail) {
480 if (msg) DeleteRexxMsg(msg);
481 doerror(ERROR_NO_FREE_STORE);
482 return;
485 /* Forbid() to find the port */
486 Forbid();
487 if (!(port=FindPort(dir->custhandler))) {
488 char message[200];
490 /* Port was not out there; put up an error requester */
491 lsprintf(message,globstring[STR_CUSTPORT_NOT_FOUND],dir->custhandler);
492 simplerequest(message,str_okaystring,NULL);
494 /* Clear message and return */
495 ClearRexxMsg(msg,4);
496 DeleteRexxMsg(msg);
497 Permit();
498 return;
501 /* Turn busy pointer on and send the message */
502 busy();
503 PutMsg(port,(struct Message *)msg);
505 Permit();
506 SetSignal(0,INPUTSIG_ABORT);
508 FOREVER {
509 /* If abort sequence hit, break out immediately. The message is now
510 lost to us, we can never free it */
511 if ((Wait(1<<general_port->mp_SigBit|INPUTSIG_ABORT))&INPUTSIG_ABORT) {
512 status_haveaborted=status_justabort=0;
513 break;
516 /* If message has been replied, free it and break out */
517 if (reply=(struct RexxMsg *)GetMsg(general_port)) {
518 ClearRexxMsg(msg,4);
519 DeleteRexxMsg(msg);
520 break;
523 unbusy();
524 okay();
527 /* Opens the "special" dir in the window for a custom list */
529 void makespecialdir(win,title)
530 int win;
531 char *title;
533 freedir(dopus_specialwin[win],win);
534 if (dopus_curwin[win]!=dopus_specialwin[win]) {
535 dopus_oldwin[win]=dopus_curwin[win];
536 dopus_curwin[win]=dopus_specialwin[win];
538 strcpy(dopus_curwin[win]->diskname,title);
539 str_pathbuffer[win][0]=0;
540 checkdir(str_pathbuffer[win],&path_strgadget[win]);
541 freedir(dopus_curwin[win],win);
542 #ifdef __SASC__
543 dopus_curwin[win]->diskfree = i64_atoi( "-1" );
544 dopus_curwin[win]->disktot = i64_atoi( "-1" );
545 dopus_curwin[win]->diskblock = -1;
546 #else
547 dopus_curwin[win]->diskfree=dopus_curwin[win]->disktot=dopus_curwin[win]->diskblock=-1;
548 #endif
551 /* Checks buffers to see if they need re-reading */
553 void check_old_buffer(win)
554 int win;
556 int reread=0;
558 if (config->dirflags&DIRFLAGS_REREADOLD && dopus_curwin[win]->directory[0]) {
559 if (dopus_curwin[win]->firstentry &&
560 ((dopus_curwin[win]->firstentry->type==ENTRY_CUSTOM) ||
561 (dopus_curwin[win]->firstentry->type==ENTRY_DEVICE) ||
562 (dopus_curwin[win]->flags & DWF_ARCHIVE))) return;
563 else {
564 struct FileInfoBlock __aligned testinfo;
566 main_proc->pr_WindowPtr=(APTR)-1;
567 if (lockandexamine(dopus_curwin[win]->directory,&testinfo)) {
568 if (CompareDate(&dopus_curwin[win]->dirstamp,&testinfo.fib_Date)<0)
569 reread=1;
570 else if (!(config->dirflags&DIRFLAGS_EXPANDPATHS) &&
571 dopus_curwin[win]->volumename[0]) {
573 char rootname[256];
575 strcpy(rootname,dopus_curwin[win]->directory);
576 if (getroot(rootname,NULL) &&
577 (strcmp(rootname,dopus_curwin[win]->volumename))!=0)
578 reread=1;
581 if (config->errorflags&ERROR_ENABLE_DOS) main_proc->pr_WindowPtr=(APTR)Window;
583 if (reread) {
584 struct DirWindowPars notifypars;
586 notifypars.reselection_list=NULL;
587 makereselect(&notifypars,win);
588 startgetdir(win,SGDFLAGS_REREADINGOLD);
589 doreselect(&notifypars,0);
590 makereselect(&notifypars,-1);
595 /* Refresh the display of a window */
597 void refreshwindow(win,type)
598 int win,type;
600 if (win>-1) {
601 if (dopus_curwin[win]->offset>dopus_curwin[win]->total-scrdata_dispwin_lines)
602 dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
603 if (dopus_curwin[win]->offset<0)
604 dopus_curwin[win]->offset=0;
606 if (type&1) {
607 fixprop(win);
608 fixhorizprop(win);
610 if (type&2) displayname(win,1);
611 dopus_curwin[win]->oldoff=dopus_curwin[win]->oldhoff=-1;
612 displaydir(win);
616 /* Move to a buffer */
618 void go_to_buffer(win,dir)
619 int win;
620 struct DirectoryWindow *dir;
622 endnotify(win);
623 dopus_curwin[win]=dir;
624 strcpy(str_pathbuffer[win],dir->directory);
625 checkdir(str_pathbuffer[win],&path_strgadget[win]);
626 checksize(win);
627 check_old_buffer(win);
628 refreshwindow(win,1);
629 doselinfo(win);
630 startnotify(win);