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.
33 /* Allocate or free directory buffers as necessary to achieve desired
34 buffer count in each window */
36 void allocdirbuffers(newnum
)
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
++) {
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;
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
)) {
64 dopus_firstwin
[win
]=next
;
65 dopus_curwin
[win
]=next
;
70 next
->next
=dopus_firstwin
[win
];
71 dopus_firstwin
[win
]->last
=next
;
74 ++data_buffer_count
[win
];
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
)
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
);
106 strcpy(str_pathbuffer
[data_active_window
],dirbuf
);
107 startgetdir(data_active_window
,SGDFLAGS_CANMOVEEMPTY
);
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
)
121 struct DirectoryWindow
*dir
=dopus_curwin
[win
],*oldestdir
;
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) {
140 oldestdir
=dir
=dopus_curwin
[win
];
141 for (a
=0;a
<data_buffer_count
[win
];a
++) {
142 if (!dir
->directory
[0])
147 if (CompareDates(&oldestdir
->dirstamp
,&dir
->dirstamp
)<0) oldestdir
=dir
;
152 dopus_curwin
[win
]=dir
;
155 /* Sets up and reads a new directory */
157 void startgetdir(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
));
173 refreshwindow(win
,0);
176 /* Moves forward or backward a buffer and refreshes display */
178 void incrementbuf(win
,dir
,show
)
182 strcpy(str_pathbuffer
[win
],dopus_curwin
[win
]->directory
);
183 checkdir(str_pathbuffer
[win
],&path_strgadget
[win
]);
185 check_old_buffer(win
);
188 refreshwindow(win
,1);
194 /* Copies the contents of one window to another */
196 void copydirwin(sourcewin
,destwin
,dest
)
197 struct DirectoryWindow
*sourcewin
,*destwin
;
200 struct Directory
*copy
;
202 if (status_iconified
) return;
204 freedir(destwin
,dest
);
205 copy
=sourcewin
->firstentry
;
206 strcpy(destwin
->realdevice
,sourcewin
->realdevice
);
208 if (!(addfile(destwin
,dest
,copy
->name
,copy
->size
,copy
->type
,©
->date
,
209 copy
->comment
,copy
->protection
,copy
->subtype
,FALSE
,copy
->dispstr
,NULL
,
210 copy
->owner_id
,copy
->group_id
))) break;
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
]);
222 last_selected_entry
=NULL
;
227 /* Swaps the contents of the two windows */
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
]);
253 /* Moves forwards or backwards a directory */
255 void advancebuf(win
,dir
)
261 if (!checkcurrentbuffer(win
)) {
263 for (a
=0;a
<dir
;a
++) dopus_curwin
[win
]=dopus_curwin
[win
]->next
;
266 for (a
=dir
;a
<0;a
++) dopus_curwin
[win
]=dopus_curwin
[win
]->last
;
271 /* Clears the contents of all unshown buffers */
276 struct DirectoryWindow
*dir
;
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
) {
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
)
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
;
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
) {
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]) {
326 (testlock
=Lock(dir
->directory
,ACCESS_READ
))) {
327 if (CompareLock(lock
,testlock
)==LOCK_SAME
) founddir
=1;
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
);
341 if (canchecklocks
) checklocks
=1;
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
352 void renamebuffers(old
,new)
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
]);
370 int replacepart(string
,old
,new)
371 char *string
,*old
,*new;
373 int oldlen
,stringlen
;
377 if (Strnicmp(string
,old
,oldlen
)) return(0);
378 if ((stringlen
=strlen(string
))>oldlen
) {
380 strncpy(tempbuf
,&string
[oldlen
],stringlen
);
381 tempbuf
[stringlen
]=0;
385 if (stringlen
>0) StrConcat(string
,tempbuf
,256);
389 /* Generates a list of all available buffers in a window */
391 void dolistbuffers(destwin
)
396 struct DirectoryWindow
*dir
;
399 if (status_iconified
) return;
400 makespecialdir(destwin
,globstring
[STR_BUFFER_LIST_TITLE
]);
402 busy(); b
=0/*scrdata_dispwin_nchars[destwin]*/; name
[0]=0;
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));
417 b
*=scrdata_font_xsize
;
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);
427 /* Check if buffer is a special buffer, and return to normal if so */
429 int checkcurrentbuffer(win
)
432 if (dopus_curwin
[win
]==dopus_specialwin
[win
]) {
433 dopus_curwin
[win
]=dopus_oldwin
[win
];
439 /* Send message to custom entry handler */
441 void userentrymessage(dir
,entry
,type
)
442 struct DirectoryWindow
*dir
;
443 struct Directory
*entry
;
446 struct RexxMsg
*msg
,*reply
;
447 struct MsgPort
*port
;
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;
456 /* Set message type (and argument count of 4) */
457 msg
->rm_Action
=RXFUNC
|4;
459 /* Fill out argument pointers.
461 Arg0 = operation type
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
475 if (!(FillRexxMsg(msg
,4,9))) fail
=1;
478 /* If we failed to create the message properly, release it and return */
480 if (msg
) DeleteRexxMsg(msg
);
481 doerror(ERROR_NO_FREE_STORE
);
485 /* Forbid() to find the port */
487 if (!(port
=FindPort(dir
->custhandler
))) {
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 */
501 /* Turn busy pointer on and send the message */
503 PutMsg(port
,(struct Message
*)msg
);
506 SetSignal(0,INPUTSIG_ABORT
);
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;
516 /* If message has been replied, free it and break out */
517 if (reply
=(struct RexxMsg
*)GetMsg(general_port
)) {
527 /* Opens the "special" dir in the window for a custom list */
529 void makespecialdir(win
,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
);
543 dopus_curwin
[win
]->diskfree
= i64_atoi( "-1" );
544 dopus_curwin
[win
]->disktot
= i64_atoi( "-1" );
545 dopus_curwin
[win
]->diskblock
= -1;
547 dopus_curwin
[win
]->diskfree
=dopus_curwin
[win
]->disktot
=dopus_curwin
[win
]->diskblock
=-1;
551 /* Checks buffers to see if they need re-reading */
553 void check_old_buffer(win
)
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;
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)
570 else if (!(config
->dirflags
&DIRFLAGS_EXPANDPATHS
) &&
571 dopus_curwin
[win
]->volumename
[0]) {
575 strcpy(rootname
,dopus_curwin
[win
]->directory
);
576 if (getroot(rootname
,NULL
) &&
577 (strcmp(rootname
,dopus_curwin
[win
]->volumename
))!=0)
581 if (config
->errorflags
&ERROR_ENABLE_DOS
) main_proc
->pr_WindowPtr
=(APTR
)Window
;
584 struct DirWindowPars notifypars
;
586 notifypars
.reselection_list
=NULL
;
587 makereselect(¬ifypars
,win
);
588 startgetdir(win
,SGDFLAGS_REREADINGOLD
);
589 doreselect(¬ifypars
,0);
590 makereselect(¬ifypars
,-1);
595 /* Refresh the display of a window */
597 void refreshwindow(win
,type
)
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;
610 if (type
&2) displayname(win
,1);
611 dopus_curwin
[win
]->oldoff
=dopus_curwin
[win
]->oldhoff
=-1;
616 /* Move to a buffer */
618 void go_to_buffer(win
,dir
)
620 struct DirectoryWindow
*dir
;
623 dopus_curwin
[win
]=dir
;
624 strcpy(str_pathbuffer
[win
],dir
->directory
);
625 checkdir(str_pathbuffer
[win
],&path_strgadget
[win
]);
627 check_old_buffer(win
);
628 refreshwindow(win
,1);