/*

Directory Opus 4
Original GPL release version 4.12
Copyright 1993-2000 Jonathan Potter

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

All users of Directory Opus 4 (including versions distributed
under the GPL) are entitled to upgrade to the latest version of
Directory Opus version 5 at a reduced price. Please see
http://www.gpsoft.com.au for more information.

The release of Directory Opus 4 under the GPL in NO WAY affects
the existing commercial status of Directory Opus 5.

*/

#include "DOpus.h"

struct Directory *selectedentry;

void doselection(win,state)
int win,state;
{
	int
		a,b,c,d,e,x,y,ox,oy,fa,la,juststart,atot,drag,offx,offy,candrag,
		comp=-1,oc,gad,multidrag=0,type,okrepeatdrag=0;
	ULONG class;
	USHORT code,qual;
	char buf[40],*ptr;
	struct Directory *next;

	candrag=drag=(config->generalflags&GENERAL_DRAG && drag_bob_buffer)?1:0;
	a=0; atot=dopus_curwin[win]->total-scrdata_dispwin_lines;
	a=makeactive(win,1);
	if (dopus_curwin[win]->total==0) return;
	ox=x=Window->MouseX; oy=y=Window->MouseY; selectedentry=NULL;
	if (!a) {
		a=(y-scrdata_dirwin_ypos[data_active_window])/scrdata_font_ysize;
		if (drag) {
			offx=x-scrdata_dirwin_xpos[data_active_window];
			if (offx<0) offx=0;
			else if (offx>drag_sprite.Width*16) offx=drag_sprite.Width*16;
			offy=y-(scrdata_dirwin_ypos[data_active_window]+(a*scrdata_font_ysize));
		}
		if ((b=select(win,a))==2) {
			return;
		}
		if (!b || !selectedentry) drag=0;
		a=juststart=0;
		Window->Flags|=WFLG_REPORTMOUSE;
		FOREVER {
			while (getintuimsg()) {
gotmsgloop:
				class=IMsg->Class; code=IMsg->Code; qual=IMsg->Qualifier;
				ReplyMsg((struct Message *) IMsg);
getcoordsloop:
				x=Window->MouseX; y=Window->MouseY;
				okrepeatdrag=0;
				if (class==MOUSEBUTTONS) {
					if (code==MENUDOWN && candrag && selectedentry) {
						status_haveaborted=status_justabort=0;
						if (drag!=2) goto startdragging;
						else {
							drag=0;
							goto enddragging;
						}
					}
					else if (code==SELECTUP) {
						a=1;
						break;
					}
				}
				else if (class==MOUSEMOVE) {
					if (drag==2) {
						if (x!=ox || y!=oy) {
							if (scr_gadget_rows && dopus_curgadbank) {
								oc=gadgetfrompos(x,y); gad=oc+(data_gadgetrow_offset*7);
								if (oc>-1 && !(isvalidgad(&dopus_curgadbank->gadgets[gad]))) oc=-1;
								if (oc!=comp) {
									RemIBob(&drag_bob,main_rp,ViewPortAddress(Window));
									if (comp>-1) dragcompgad(comp,0);
									if (oc>-1 && isvalidgad(&dopus_curgadbank->gadgets[gad])) {
										dragcompgad(oc,1);
										comp=oc;
									}
									else comp=-1;
									AddBob(&drag_bob,main_rp);
								}
							}
							drag_sprite.X=x-offx; drag_sprite.Y=y-offy;
							SortGList(main_rp);
							DrawGList(main_rp,ViewPortAddress(Window));
							WaitTOF();
						}
						ox=x; oy=y;
					}
					else {
						fa=(y-scrdata_dirwin_ypos[data_active_window])/scrdata_font_ysize; la=(oy-scrdata_dirwin_ypos[data_active_window])/scrdata_font_ysize;
						if (fa==la && drag && selectedentry) {
							if (x<scrdata_dirwin_xpos[data_active_window] || x>scrdata_dirwin_xpos[data_active_window]+scrdata_dirwin_width[data_active_window]) {
startdragging:
								ptr=NULL;
								if (qual&IEQUALIFIER_ANYSHIFT && dopus_curwin[win]->filesel>1) {
									multidrag=1;
									lsprintf(buf,globstring[STR_MULTI_DRAG],dopus_curwin[win]->filesel);
									ptr=buf;
									type=-1;
								}
								else {
									if (selectedentry->type==ENTRY_CUSTOM) {
										switch (selectedentry->subtype) {
											case CUSTOMENTRY_BUFFERLIST:
												ptr=selectedentry->comment;
												break;
											case CUSTOMENTRY_DIRTREE:
												ptr=selectedentry->dispstr;
												break;
											case CUSTOMENTRY_USER:
												if (selectedentry->size&CUSTENTRY_CANSELECT)
													ptr=selectedentry->comment;
												break;
										}
									}
									else ptr=selectedentry->name;
									type=selectedentry->type;
								}
								if (ptr) {
									dotaskmsg(clockmsg_port,CLOCK_ACTIVE,0,0,NULL,0);
									SetAPen(&drag_bob_rastport,
										(type<=ENTRY_FILE ||
											(type==ENTRY_DEVICE &&
											(selectedentry->size==DLT_DEVICE || selectedentry->size==DLT_VOLUME)))?
										screen_pens[config->filesselfg].pen:
											screen_pens[config->dirsselfg].pen);
									SetRast(&drag_bob_rastport,
										(type<=ENTRY_FILE ||
											(type==ENTRY_DEVICE &&
											(selectedentry->size==DLT_DEVICE || selectedentry->size==DLT_VOLUME)))?
										screen_pens[config->filesselbg].pen:
											screen_pens[config->dirsselbg].pen);
									Move(&drag_bob_rastport,0,scr_font[FONT_DIRS]->tf_Baseline);
									c=(drag_sprite.Width*16)/scrdata_font_xsize;
									d=strlen(ptr);
									if (d>c) e=d-c;
									else {
										e=0;
										c=d;
									}
									Text(&drag_bob_rastport,&ptr[e],c);
									drag_sprite.X=x-offx; drag_sprite.Y=y-offy;
									AddBob(&drag_bob,main_rp);
									SortGList(main_rp);
									DrawGList(main_rp,ViewPortAddress(Window));
									WaitTOF();
									drag=2; y=-1;
								}
							}
						}
						else {
							if (drag) drag=0;
							if (la<fa) {
								++fa; ++la;
								d=la; la=fa; fa=d;
							}
							if (y>=scrdata_dispwin_ypos && y<scrdata_dispwin_height+scrdata_dispwin_ypos) {
								if (state) {
									for (d=fa;d<la;d++) defselect(win,d,b);
								}
							}
							else if (y<scrdata_dispwin_ypos) {
								if (juststart!=-1) {
									if (fa<0) fa=0; if (la>=scrdata_dispwin_lines) la=scrdata_dispwin_lines;
									if (state) {
										for (d=fa;d<la;d++) defselect(win,d,b);
										defselect(win,0,b);
									}
									juststart=-1;
								}
								if (dopus_curwin[win]->offset==0) continue;
								verticalscroll(win,-1);
								if (state) defselect(win,0,b);
								okrepeatdrag=1;
							}
							else if (y>=scrdata_dispwin_height+scrdata_dispwin_ypos) {
								if (juststart!=1) {
									if (fa<0) fa=0; if (la>=scrdata_dispwin_lines) la=scrdata_dispwin_lines;
									if (state) {
										for (d=fa;d<la;d++) defselect(win,d,b);
										defselect(win,scrdata_dispwin_lines-1,b);
									}
									juststart=1;
								}
								if (dopus_curwin[win]->offset==atot) continue;
								verticalscroll(win,1);
								if (state) defselect(win,scrdata_dispwin_lines-1,b);
								okrepeatdrag=1;
							}
						}
						oy=y;
					}
				}
			}
			if (a) break;
			if (getintuimsg()) goto gotmsgloop;
			if (okrepeatdrag) goto getcoordsloop;
			Wait(1<<Window->UserPort->mp_SigBit);
		}
		if (drag==2) {
enddragging:
			RemIBob(&drag_bob,main_rp,ViewPortAddress(Window));
			if (comp>-1) dragcompgad(comp,0);
			dotaskmsg(clockmsg_port,CLOCK_ACTIVE,1,0,NULL,0);
			if (x>=scrdata_dirwin_xpos[1-data_active_window] &&
				x<=scrdata_dirwin_xpos[1-data_active_window]+scrdata_dirwin_width[1-data_active_window] &&
				y>=scrdata_dirwin_ypos[1-data_active_window] &&
				y<=scrdata_dirwin_ypos[1-data_active_window]+scrdata_dirwin_height && drag==2) {
				if (multidrag) {
					last_selected_entry=dopus_curwin[win]->firstentry;
					while (last_selected_entry) {
						if (status_haveaborted || status_justabort) {
							myabort();
							break;
						}
						next=last_selected_entry->next;
						if (last_selected_entry->type<=ENTRY_FILE && last_selected_entry->selected) {
							CurrentTime(&time_previous_sec,&time_previous_micro);
							time_current_sec=time_previous_sec;
							time_current_micro=time_previous_micro;
							makeactive(1-data_active_window,1);
						}
						last_selected_entry=next;
					}
				}
				else {
					time_previous_sec=time_current_sec;
					time_previous_micro=time_current_micro;
					last_selected_entry=selectedentry;
					makeactive(1-data_active_window,1);
				}
			}
			else if (comp>-1) {
				gad=comp+(data_gadgetrow_offset*7);
				if (dopus_curgadbank && isvalidgad(&dopus_curgadbank->gadgets[gad])) {
					if (multidrag) {
						last_selected_entry=NULL;
						func_single_file[0]=0;
						status_flags|=STATUS_GLOBALFILE;
					}
					else {
						last_selected_entry=selectedentry;
						strcpy(func_single_file,selectedentry->name);
						if (selectedentry->selected) unselect(data_active_window,selectedentry);
					}
					dofunctionstring(dopus_curgadbank->gadgets[gad].function,
						dopus_curgadbank->gadgets[gad].name,
						NULL,(struct dopusfuncpar *)&dopus_curgadbank->gadgets[gad].which);
					status_flags&=~STATUS_GLOBALFILE;
					if (!multidrag) checkselection(selectedentry);
				}
			}
		}
		Window->Flags&=~WFLG_REPORTMOUSE;
	}
}

void dormbscroll(win)
int win;
{
	ULONG class;
	USHORT code;
	int x,y,d,a,ret=0;
	struct Directory *temp;

	if (data_active_window!=win) {
		makeactive(win,0);
		ret=1;
	}

	if (dopus_curwin[win]->total>0 && status_flags&STATUS_IANSCRAP) {
		CurrentTime(&time_current_sec,&time_current_micro);
		y=Window->MouseY;
		a=(y-scrdata_dirwin_ypos[data_active_window]-2)/scrdata_font_ysize;
		if (a<scrdata_dispwin_lines) {
			a+=dopus_curwin[win]->offset;
			if (a<=dopus_curwin[win]->total) {
				temp=dopus_curwin[win]->firstentry;
				while (a--) temp=temp->next;
				if (temp && temp->type<=ENTRY_FILE && temp->selected &&
					(DoubleClick(time_previous_sec,time_previous_micro,
						time_current_sec,time_current_micro)) &&
					last_selected_entry==temp &&
					config->generalflags&GENERAL_DOUBLECLICK) {
					unselect(win,temp);
					ftype_doubleclick(str_pathbuffer[win],temp->name,0);
					unbusy();
					time_previous_sec=0;
					return;
				}
			}
		}
		if (ret) return;
	}

	FOREVER {
		while (!getintuimsg()) {
			x=Window->MouseX; y=Window->MouseY;
			d=0;
			if (y<scr_scroll_borders[win].MinY) {
				verticalscroll(win,-1);
				if (y>scr_scroll_borders[win].MinY-(scrdata_font_ysize*4)) d=1;
			}
			else if (y>scr_scroll_borders[win].MaxY) {
				verticalscroll(win,1);
				if (y<scr_scroll_borders[win].MaxY+(scrdata_font_ysize*4)) d=1;
			}
			else if (x<scr_scroll_borders[win].MinX) horizontalscroll(win,-1);
			else if (x>scr_scroll_borders[win].MaxX) horizontalscroll(win,1);
			if (d) Delay(d);
		}
		class=IMsg->Class; code=IMsg->Code;
		ReplyMsg((struct Message *) IMsg);
		if (class==MOUSEBUTTONS && code==MENUUP) break;
	}
}

select(win,o)
int win,o;
{
	int a,dbclick=0,sel=1,foundcount;
	char sbuf[32],*dir;
	struct Directory *temp,*temp2;

	a=o+dopus_curwin[win]->offset;
	if (o>=scrdata_dispwin_lines || a>=dopus_curwin[win]->total) return(0);
	temp=dopus_curwin[win]->firstentry;
	while (a--) temp=temp->next;
	selectedentry=temp;
	if (temp && ENTRYTYPE(temp->type)!=ENTRY_CUSTOM ||
		temp->subtype!=CUSTOMENTRY_USER || temp->size&CUSTENTRY_CANSELECT) {
		sel=temp->selected;
		temp->selected=sel?FALSE:TRUE;
		updateselectinfo(temp,win,1);
		if (!status_iconified) {
			display_entry(temp,win,
				scrdata_dirwin_xpos[win],
				scrdata_font_baseline+(scrdata_font_ysize*o)+scrdata_dirwin_ypos[win]);
			if (config->iconflags&ICONFLAG_AUTOSELECT) {
				StrCombine(sbuf,temp->name,".info",31);
				if ((temp2=findfile(dopus_curwin[win],sbuf,&foundcount))) {
					if (temp2->selected!=temp->selected) {
						temp2->selected=temp->selected;
						updateselectinfo(temp2,win,1);
						if (foundcount>=dopus_curwin[win]->offset &&
							foundcount<dopus_curwin[win]->offset+scrdata_dispwin_lines) {
							o=foundcount-dopus_curwin[win]->offset;
							display_entry(temp2,win,
								scrdata_dirwin_xpos[win],
								scrdata_font_baseline+(scrdata_font_ysize*o)+scrdata_dirwin_ypos[win]);
						}
					}
				}
			}
		}

/*
		if (last_selected_entry!=temp ||
			!(dbclick=DoubleClick(time_previous_sec,time_previous_micro,
				time_current_sec,time_current_micro))) {
			last_selected_entry=temp;
		}
		time_previous_sec=time_current_sec;
		time_previous_micro=time_current_micro;
*/
		
		if (sel) {
			dbclick=DoubleClick(time_previous_sec,time_previous_micro,
				time_current_sec,time_current_micro);
		}
		else {
			dbclick=-1;
			time_previous_sec=time_current_sec;
			time_previous_micro=time_current_micro;
		}

		switch (ENTRYTYPE(temp->type)) {
			case ENTRY_DEVICE:
			case ENTRY_DIRECTORY:
				if (dbclick==-1) last_selected_entry=temp;
				else if (dbclick && last_selected_entry==temp) {
					dir=dopus_curwin[win]->directory;
					advancebuf(win,1);
					if (temp->type==ENTRY_DEVICE) strcpy(str_pathbuffer[win],temp->name);
					else {
						strcpy(str_pathbuffer[win],dir);
						TackOn(str_pathbuffer[win],temp->name,256);
					}
					startgetdir(win,SGDFLAGS_CANMOVEEMPTY|SGDFLAGS_CANCHECKBUFS);
					time_previous_sec=0;
					return(2);
				}
				break;

			case ENTRY_CUSTOM:
				if (dbclick==-1) last_selected_entry=temp;
				else if (dbclick && last_selected_entry==temp) {
					if (temp->subtype==CUSTOMENTRY_BUFFERLIST ||
						temp->subtype==CUSTOMENTRY_DIRTREE) {
						if (temp->subtype==CUSTOMENTRY_BUFFERLIST)
							bringinbuffer(last_selected_entry->dispstr,win,1);
						else {
							strcpy(str_pathbuffer[win],last_selected_entry->dispstr);
							startgetdir(win,SGDFLAGS_CANMOVEEMPTY|SGDFLAGS_CANCHECKBUFS);
						}
						time_previous_sec=0;
						return(2);
					}
					else if (temp->subtype==CUSTOMENTRY_USER) {
						userentrymessage(dopus_curwin[win],temp,USERENTRY_DOUBLECLICK);
						time_previous_sec=0;
						return(2);
					}
				}
				break;

			case ENTRY_FILE:
				if (dbclick==-1) last_selected_entry=temp;
				else if (dbclick && last_selected_entry==temp) {
					if (config->generalflags&GENERAL_DOUBLECLICK) {
						ftype_doubleclick(str_pathbuffer[win],temp->name,1);
						unbusy();
						time_previous_sec=0;
						return(2);
					}
				}
				break;
		}
	}
	return(!sel);
}

unselect(win,file)
int win;
struct Directory *file;
{
	int a=0;
	struct Directory *t;

	if (win==-1 || !file->selected) return(0);
	t=dopus_curwin[win]->firstentry;
	while (t!=file && t) {
		++a;
		t=t->next;
	}
	if (!t) return(0);
	switch (ENTRYTYPE(file->type)) {
		case ENTRY_DIRECTORY:
		case ENTRY_DEVICE:
			--dopus_curwin[win]->dirsel;
			if (file->type>0 && file->size!=-1) dopus_curwin[win]->bytessel-=file->size;
			break;
		case ENTRY_FILE:
			--dopus_curwin[win]->filesel;
			dopus_curwin[win]->bytessel-=file->size;
			break;
	}
	file->selected=FALSE;
	if (a<dopus_curwin[win]->offset ||
		a>(dopus_curwin[win]->offset+scrdata_dispwin_lines-1)) return(0);
	a-=dopus_curwin[win]->offset;
	if (!status_iconified) {
		display_entry(t,win,
			scrdata_dirwin_xpos[win],
			scrdata_font_baseline+(scrdata_font_ysize*a)+scrdata_dirwin_ypos[win]);
	}
	return(1);
}

void defselect(win,o,state)
int win,o,state;
{
	int a,foundcount;
	struct Directory *temp,*temp2;
	char sbuf[32];

	if (o<0 || o>scrdata_dispwin_lines-1) return;
	a=o+dopus_curwin[win]->offset;
	if (a>=dopus_curwin[win]->total) return;
	temp=dopus_curwin[win]->firstentry;
	while (a--) temp=temp->next;
	if (state) selectedentry=temp;
	else selectedentry=NULL;
	if (temp && ENTRYTYPE(temp->type)!=ENTRY_CUSTOM ||
		temp->subtype!=CUSTOMENTRY_USER || temp->size&CUSTENTRY_CANSELECT) {
		if (temp->selected!=state) {
			temp->selected=state;
			updateselectinfo(temp,win,1);
			if (!status_iconified) {
				display_entry(temp,win,
					scrdata_dirwin_xpos[win],
					scrdata_font_baseline+(scrdata_font_ysize*o)+scrdata_dirwin_ypos[win]);
			}
		}
		if (config->iconflags&ICONFLAG_AUTOSELECT) {
			StrCombine(sbuf,temp->name,".info",31);
			if ((temp2=findfile(dopus_curwin[win],sbuf,&foundcount))) {
				if (temp2->selected!=temp->selected) {
					temp2->selected=temp->selected;
					updateselectinfo(temp2,win,1);
					if (foundcount>=dopus_curwin[win]->offset &&
						foundcount<dopus_curwin[win]->offset+scrdata_dispwin_lines) {
						if (!status_iconified) {
							o=foundcount-dopus_curwin[win]->offset;
							display_entry(temp2,win,
								scrdata_dirwin_xpos[win],
								scrdata_font_baseline+(scrdata_font_ysize*o)+scrdata_dirwin_ypos[win]);
						}
					}
				}
			}
		}
	}
}

void globalselect(win,all)
int win,all;
{
	struct Directory *temp;

	if ((temp=dopus_curwin[win]->firstentry) && temp->type!=ENTRY_CUSTOM) {
		while (temp) {
/*
			if (temp->type!=ENTRY_CUSTOM || temp->subtype!=CUSTOMENTRY_USER ||
				temp->size&CUSTENTRY_CANSELECT) temp->selected=all;
*/
			temp->selected=all;
			temp=temp->next;
		}
		if (all) {
			dopus_curwin[win]->filesel=dopus_curwin[win]->filetot;
			dopus_curwin[win]->dirsel=dopus_curwin[win]->dirtot;
			dopus_curwin[win]->bytessel=dopus_curwin[win]->bytestot;
		}
		else {
			dopus_curwin[win]->filesel=0;
			dopus_curwin[win]->dirsel=0;
			dopus_curwin[win]->bytessel=0;
		}
		doselinfo(win);
	}
}

void updateselectinfo(temp,win,show)
struct Directory *temp;
int win,show;
{
	if (temp->selected) {
		switch (ENTRYTYPE(temp->type)) {
			case ENTRY_DIRECTORY:
				if (temp->size!=-1) dopus_curwin[win]->bytessel+=temp->size;
			case ENTRY_DEVICE:
				++dopus_curwin[win]->dirsel;
				break;
			case ENTRY_FILE:
				++dopus_curwin[win]->filesel;
				dopus_curwin[win]->bytessel+=temp->size;
				break;
		}
		if (show) {
			if (config->generalflags&GENERAL_DISPLAYINFO) doinfodisplay(temp,TRUE);
			else doselinfo(data_active_window);
		}
	}
	else {
		switch (ENTRYTYPE(temp->type)) {
			case ENTRY_DIRECTORY:
				if (temp->size!=-1) dopus_curwin[win]->bytessel-=temp->size;
			case ENTRY_DEVICE:
				--dopus_curwin[win]->dirsel;
				break;
			case ENTRY_FILE:
				--dopus_curwin[win]->filesel;
				dopus_curwin[win]->bytessel-=temp->size;
				break;
		}
		if (show) doselinfo(data_active_window);
	}
}

void globaltoggle(win)
int win;
{
	struct Directory *temp;

	temp=dopus_curwin[win]->firstentry;
	while (temp) {
		switch (ENTRYTYPE(temp->type)) {
			case ENTRY_FILE:
				if (temp->selected) {
					dopus_curwin[win]->bytessel-=temp->size;
					--dopus_curwin[win]->filesel;
					temp->selected=0;
				}
				else {
					dopus_curwin[win]->bytessel+=temp->size;
					++dopus_curwin[win]->filesel;
					temp->selected=1;
				}
				break;
			case ENTRY_DIRECTORY:
				if (temp->selected) {
					if (temp->size>0) dopus_curwin[win]->bytessel-=temp->size;
					--dopus_curwin[win]->dirsel;
					temp->selected=0;
				}
				else {
					if (temp->size>0) dopus_curwin[win]->bytessel+=temp->size;
					++dopus_curwin[win]->dirsel;
					temp->selected=1;
				}
				break;
		}
		temp=temp->next;
	}
	doselinfo(win);
}

void doselect(rexx)
int rexx;
{
	char buf[160];
	int boobs,prot[2];
	struct DateStamp ds1,ds2;
	int selecttype;

	if (dopus_curwin[data_active_window]->total==0 ||
		dopus_curwin[data_active_window]->firstentry->type==ENTRY_CUSTOM) return;

	if (!rexx) {
		boobs=getselectdata(str_select_pattern,&selecttype);
	}
	else {
		boobs=rexx_arg_value[0]; selecttype=rexx_arg_value[1];
		strcpy(str_select_pattern[selecttype],rexx_args[0]);
	}
	if (boobs) {
		if (dopus_curwin[data_active_window]->total==0) return;
		switch (selecttype) {
			case 0:
				LParsePatternI(str_select_pattern[0],buf);
				wildselect(buf,boobs,1);
				findfirstsel(data_active_window,-2);
				break;
			case 1:
				if (str_select_pattern[1][0]==0) break;
				getseldatestamps(str_select_pattern[1],&ds1,&ds2);
				dateselect(&ds1,&ds2,boobs,1);
				findfirstsel(data_active_window,-2);
				break;
			case 2:
				if (str_select_pattern[2][0]==0) break;
				getprotselvals(str_select_pattern[2],prot);
				protselect(prot[0],prot[1],boobs,1);
				findfirstsel(data_active_window,-2);
				break;
		}
	}
}

void getseldatestamps(buf,ds1,ds2)
char *buf;
struct DateStamp *ds1,*ds2;
{
	char datebuf[2][85],timebuf[2][85],*ptr;
	int a,b;

	datebuf[0][0]=datebuf[1][0]=timebuf[0][0]=timebuf[1][0]=a=b=0;
	ptr=parsedatetime(str_select_pattern[1],datebuf[0],timebuf[0],&a);
	strtostamp(datebuf[0],timebuf[0],ds1);
	if (!a) {
		strcpy(datebuf[1],datebuf[0]);
		strcpy(timebuf[1],"23:59:59");
	}
	else if (a==-1) {
		strcpy(datebuf[1],datebuf[0]);
		strcpy(timebuf[1],timebuf[0]);
	}
	else parsedatetime(ptr,datebuf[1],timebuf[1],&b);
	strtostamp(datebuf[1],timebuf[1],ds2);
	ds1->ds_Tick=((ds1->ds_Tick/50)*50);
	ds2->ds_Tick=((ds2->ds_Tick/50)*50)+49;
}

void getprotselvals(buf,prot)
char *buf;
int *prot;
{
	int a,b,c,notflag=0;
	char ch;

	prot[0]=prot[1]=0;
	b=strlen(buf);
	for (a=0;a<b;a++) {
		ch=tolower(buf[a]);
		if (ch=='-') notflag=1;
		else if (ch=='+') notflag=0;
		else {
			for (c=0;c<8;c++) {
				if (ch==globstring[STR_PROTBIT_ALLBITS][c]) {
					prot[notflag]|=(1<<(7-c));
					break;
				}
			}
		}
	}
}

void wildselect(wild,boobs,and)
char *wild;
int boobs,and;
{
	char buf[256];
	struct Directory *temp;

	temp=dopus_curwin[data_active_window]->firstentry;
	if (!and) dopus_curwin[data_active_window]->dirsel=dopus_curwin[data_active_window]->filesel=dopus_curwin[data_active_window]->bytessel=0;
	while (temp) {
		if (temp->type!=ENTRY_CUSTOM || temp->subtype!=CUSTOMENTRY_USER ||
			temp->size&CUSTENTRY_CANSELECT) {
			if (!and) temp->selected=0;
			if (temp->type==ENTRY_CUSTOM) {
				if (!temp->selected && temp->comment) {
					StrToUpper(temp->comment,buf);
					if (LMatchPatternI(wild,buf)) wildselectthisone(temp,data_active_window,boobs);
				}
			}
			else {
				if (!temp->selected) {
					StrToUpper(temp->name,buf);
					if (LMatchPatternI(wild,buf)) wildselectthisone(temp,data_active_window,boobs);
				}
			}
		}
		temp=temp->next;
	}
	refreshwindow(data_active_window,0);
	doselinfo(data_active_window);
}

void dateselect(ds1,ds2,boobs,and)
struct DateStamp *ds1,*ds2;
int boobs,and;
{
	struct Directory *temp;

	temp=dopus_curwin[data_active_window]->firstentry;
	if (!and) {
		dopus_curwin[data_active_window]->dirsel=
			dopus_curwin[data_active_window]->filesel=
			dopus_curwin[data_active_window]->bytessel=0;
	}
	while (temp) {
		if (temp->type!=ENTRY_CUSTOM || temp->subtype!=CUSTOMENTRY_USER ||
			temp->size&CUSTENTRY_CANSELECT) {
			if (!and) temp->selected=0;
			if (!temp->selected &&
				CompareDate(&(temp->date),ds1)>=0 && CompareDate(ds2,&(temp->date))>=0)
				wildselectthisone(temp,data_active_window,boobs);
		}
		temp=temp->next;
	}
	refreshwindow(data_active_window,0);
	doselinfo(data_active_window);
}

void protselect(protyes,protno,boobs,and)
int protyes,protno,boobs,and;
{
	struct Directory *temp;
	int prot;

	temp=dopus_curwin[data_active_window]->firstentry;
	if (!and) dopus_curwin[data_active_window]->dirsel=dopus_curwin[data_active_window]->filesel=dopus_curwin[data_active_window]->bytessel=0;
	while (temp) {
		if (temp->type!=ENTRY_CUSTOM || temp->subtype!=CUSTOMENTRY_USER ||
			temp->size&CUSTENTRY_CANSELECT) {
			if (!and) temp->selected=0;
			if (!temp->selected) {
				prot=((~temp->protection)&15)+(temp->protection&~15);
				if ((prot&protyes)==protyes && ((prot&~protyes)&protno)==0)
					wildselectthisone(temp,data_active_window,boobs);
			}
		}
		temp=temp->next;
	}
	refreshwindow(data_active_window,0);
	doselinfo(data_active_window);
}

void wildselectthisone(temp,win,boobs)
struct Directory *temp;
int win,boobs;
{
	if (boobs==1 && temp->type!=ENTRY_DEVICE) temp->selected=1;
	else if (boobs==2 && temp->type<=ENTRY_FILE) temp->selected=1;
	else if (boobs==3 && temp->type>=ENTRY_DIRECTORY) temp->selected=1;
	if (temp->selected) {
		if (temp->type>=ENTRY_DIRECTORY) {
			++dopus_curwin[win]->dirsel;
			if (temp->size!=-1) dopus_curwin[win]->bytessel+=temp->size;
		}
		else if (temp->type<=ENTRY_FILE) {
			++dopus_curwin[win]->filesel;
			dopus_curwin[win]->bytessel+=temp->size;
		}
	}
}

void doselinfo(win)
int win;
{
	if (!dopus_curwin[win]->firstentry || dopus_curwin[win]->firstentry->type!=ENTRY_CUSTOM) {
		lsprintf(str_select_info,globstring[STR_DIRS_FILES_BYTES_COUNT],
			dopus_curwin[win]->dirsel,dopus_curwin[win]->dirtot,dopus_curwin[win]->filesel,
			dopus_curwin[win]->filetot,dopus_curwin[win]->bytessel,dopus_curwin[win]->bytestot);
	}
	else {
		switch (dopus_curwin[win]->firstentry->subtype) {
			case CUSTOMENTRY_DIRTREE:
				lsprintf(str_select_info,globstring[STR_ENTRIES_IN_TREE],dopus_curwin[win]->total);
				break;
			case CUSTOMENTRY_BUFFERLIST:
				lsprintf(str_select_info,globstring[STR_DIRS_IN_BUFFERS],dopus_curwin[win]->total);
				break;
			case CUSTOMENTRY_USER:
				lsprintf(str_select_info,globstring[STR_USER_ENTRIES],dopus_curwin[win]->total);
				break;
		}
	}
	dostatustext(str_select_info);
}

makeactive(win,state)
int win,state;
{
	if (data_active_window!=win) {
		data_active_window=win;
		return(doactive(state,1));
	}
	return(0);
}

doactive(state,showinfo)
int state,showinfo;
{
	int oe;
	char buf[256];
	struct dopusfiletype *type;
	struct dopusfuncpar par;
	struct Directory *entry;

	if (status_iconified) return(0);
	if (showinfo) doselinfo(data_active_window);
	if (last_selected_entry &&
		last_selected_entry->type<=ENTRY_FILE) {
		if (state && config->generalflags&GENERAL_DOUBLECLICK) {
			if (DoubleClick(time_previous_sec,time_previous_micro,
				time_current_sec,time_current_micro)) {
				data_active_window=1-data_active_window;
				unselect(data_active_window,last_selected_entry);
				entry=last_selected_entry;
				dostatustext(globstring[STR_INTERROGATING_FILE]);
				StrCombine(buf,str_pathbuffer[data_active_window],last_selected_entry->name,256);
				busy();
				if ((type=checkfiletype(buf,FTFUNC_CLICKMCLICK,0))) {
					char title[256];

					strcpy(func_single_file,last_selected_entry->name);
					par.which=type->which[FTFUNC_CLICKMCLICK];
					par.stack=type->stack[FTFUNC_CLICKMCLICK];
					par.key=par.qual=0; par.type=3;
					par.pri=type->pri[FTFUNC_CLICKMCLICK];
					par.delay=type->delay[FTFUNC_CLICKMCLICK];

					if (type->actionstring[FTFUNC_CLICKMCLICK][0]) {
						do_title_string(type->actionstring[FTFUNC_CLICKMCLICK],title,0,NULL);
						dostatustext(title);
					}
					else title[0]=0;

					dofunctionstring(type->function[FTFUNC_CLICKMCLICK],
						last_selected_entry->name,title,&par);
					unbusy();
					checkselection(entry);
					return(1);
				}
				unbusy();
				return(0);
			}
		}
		last_selected_entry=NULL;
	}
	for (oe=0;oe<2;oe++) displayname(oe,1);
	if (last_selected_entry &&
		last_selected_entry->type>=ENTRY_DEVICE && state) {
		if (DoubleClick(time_previous_sec,time_previous_micro,
			time_current_sec,time_current_micro)) {
			if (last_selected_entry->type==ENTRY_CUSTOM &&
				last_selected_entry->subtype==CUSTOMENTRY_USER) {
				if (last_selected_entry->size&CUSTENTRY_CANSELECT) {
					userentrymessage(dopus_curwin[1-data_active_window],last_selected_entry,USERENTRY_CLICKMCLICK);
					time_previous_sec=0;
				}
			}
			else {
				unselect(1-data_active_window,last_selected_entry);
				advancebuf(data_active_window,1);
				if (last_selected_entry->type==ENTRY_CUSTOM) {
					if (last_selected_entry->subtype==CUSTOMENTRY_BUFFERLIST) {
						bringinbuffer(last_selected_entry->dispstr,data_active_window,1);
						time_previous_sec=0;
						return(1);
					}
					else strcpy(str_pathbuffer[data_active_window],last_selected_entry->dispstr);
				}
				else {
					strcpy(str_pathbuffer[data_active_window],dopus_curwin[1-data_active_window]->directory);
					TackOn(str_pathbuffer[data_active_window],last_selected_entry->name,256);
				}
				startgetdir(data_active_window,SGDFLAGS_CANMOVEEMPTY|SGDFLAGS_CANCHECKBUFS);
				time_previous_sec=0;
				return(1);
			}
		}
	}
	return(0);
}

void unbyte(win)
int win;
{
	struct Directory *entry;

	entry=dopus_curwin[win]->firstentry;
	while (entry) {
		if (entry->selected && ENTRYTYPE(entry->type)==ENTRY_DIRECTORY &&
			entry->size!=-1) {
			setdirsize(entry,-1,win);
		}
		if (entry->next) entry=entry->next;
		else entry=NULL;
	}
	refreshwindow(win,0);
	if (win==data_active_window) doselinfo(win);
}

void checkselection(entry)
struct Directory *entry;
{
	struct Directory *temp;

	last_selected_entry=NULL; func_single_file[0]=0;
	temp=dopus_curwin[data_active_window]->firstentry;
	while (temp) {
		if (temp==entry) break;
		temp=temp->next;
	}
	if (temp && temp->selected) unselect(data_active_window,temp);
}
