{
cookperm_edit - A cookperm.txt editor for Gecko-based browsers
Copyright (c) 2004 rmn

Permission to use, copy, modify and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies, that both
the copyright notice and this permission notice appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. The author makes no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.
}


program cookperm_edit;
uses windows,kol;

const
	{=============================}
	VERSION:string='0.1.3';
	COMPILE_DATE:string='20040307';
	{=============================}

type permdata=record
	site:string;
	perm:array[0..2]of byte;
end;

var
	form1,list1,edit1:pcontrol;
	group1:array[0..2]of pcontrol;
	radio1:array[0..2,0..2]of pcontrol;
	n:word;
	fpath:string;
	data:array of permdata;

{===radio1Click===}

procedure radio1Click(dummy:pointer;Sender:PObj);
var
	a,b:byte;
begin
	for a:=0to 2do
		for b:=0to 2do
			if Sender=radio1[a,b]then
				data[list1.CurIndex+1].perm[a]:=b;
end;

{===list1Change===}

procedure list1Change;
var a:byte;
begin
	if n=0then begin
		edit1.Text:='';
		for a:=0to 2do
			group1[a].Enabled:=false;
		exit;
	end;
	edit1.Text:=data[list1.CurIndex+1].site;
	for a:=0to 2do
		radio1[a,data[list1.CurIndex+1].perm[a]].SetRadioChecked;
end;

{===form1KeyDown===}

procedure form1KeyDown(dummy:pointer;Sender:PControl;var Key:Longint;Shift:DWORD);
begin
	case Key of
		VK_F1:messagebox(form1.Handle,pchar('cookperm_edit v'+VERSION+#13#10'Compiled '+COMPILE_DATE+#13#10'Copyright (c) 2004 rmn - usual disclaimers apply'#13#10'http://www.geocities.com/rmn_km/'#13#10#13#10'Navigation:'#13#10'F2 - edit site name'#13#10'Ins - add entry'#13#10'Del - delete entry'),'About cookperm_edit',MB_ICONINFORMATION);
		VK_TAB:pcontrol(Sender).Tabulate;
	end;
end;

{===edit1KeyDown===}

procedure edit1KeyDown(dummy:pointer;Sender:PControl;var Key:Longint;Shift:DWORD);
var a:byte;
begin
	case Key of
		VK_RETURN:begin
			data[list1.CurIndex+1].site:=edit1.Text;
			list1.Items[list1.CurIndex]:=edit1.Text;
			list1.Enabled:=true;
			list1.Focused:=true;
			for a:=0to 2do
				group1[a].Enabled:=true;
			edit1.Enabled:=false;
		end;
	end;

	{handle form-wide keys as well}
	form1KeyDown(dummy,Sender,Key,Shift);
end;

{===list1KeyDown===}

procedure editsite;
var a:byte;
begin
	edit1.Enabled:=true;
	edit1.Focused:=true;
	edit1.SelectAll;
	list1.Enabled:=false;
	for a:=0to 2do
		group1[a].Enabled:=false;
end;

procedure list1KeyDown(dummy:pointer;Sender:PControl;var Key:Longint;Shift:DWORD);
var oldidx,a:word;
begin
	case Key of
		VK_F2:if n>0then editsite;
		VK_INSERT:begin
			inc(n);
			setlength(data,n*sizeof(permdata));
			data[n].site:='';
			for a:=0to 2do
				data[n].perm[a]:=0;
			list1.Add('');
			list1.CurIndex:=list1.Count-1;
			list1Change; {sync}
			editsite;
		end;
		VK_DELETE:begin
			oldidx:=list1.CurIndex;
			for a:=(list1.CurIndex+1)+1to list1.Count do begin
				data[a-1]:=data[a];
			end;
			dec(n);
			list1.Delete(list1.CurIndex);
			if oldidx=list1.Count then
				list1.CurIndex:=oldidx-1
			else
				list1.CurIndex:=oldidx;
			list1Change;
		end;
	end;

	{handle form-wide keys as well}
	form1KeyDown(dummy,Sender,Key,Shift);
end;

{===form1Resize===}

procedure form1Resize;
var a:byte;
begin
	edit1.SetPosition(form1.ClientWidth-group1[0].Width-5,5);
	for a:=0to 2do
		group1[a].SetPosition(edit1.Left,25+a*90);
	list1.SetSize(edit1.Left-10,form1.ClientHeight-list1.Top-5);
end;

{===form1Close===}

procedure form1Close(dummy:pointer;Sender:PObj;var Accept:Boolean);
var
	f:text;
	a:word;
	b:byte;
begin
	case messagebox(form1.Handle,'Save file?','Exit',MB_YESNOCANCEL+MB_ICONQUESTION)of
		IDYES:
			begin
				assignfile(f,fpath);
				rewrite(f);
				writeln(f,'# HTTP Permission File'#13#10'# http://www.netscape.com/newsref/std/cookie_spec.html'#13#10'# This is a generated file!  Do not edit.'#13#10#13#10'%0	cookie'#13#10'%1	image'#13#10'%2	popup'#13#10);
				for a:=1to n do begin
					if(data[a].perm[0]=0)and(data[a].perm[1]=0)and(data[a].perm[2]=0)then continue;
					write(f,data[a].site);
					for b:=0to 2do
						case data[a].perm[b]of
							1:write(f,'	',chr(b+ord('0')),'F');
							2:write(f,'	',chr(b+ord('0')),'T');
						end;
					writeln(f);
				end;
				close(f);
			end;
		IDCANCEL:
			Accept:=false;
	end;
end;

{===MAIN===}

var
	datpath:string;
	f:text;
	a:word;
	b:byte;
	s:string;
	nodata:boolean;
begin
	{init form}
	form1:=newform(nil,'cookperm_edit');
	form1.SetSize(400,329);
	form1.CenterOnParent;
	form1.OnResize:=tonevent(makemethod(nil,@form1Resize));
	form1.OnKeyDown:=tonkey(makemethod(nil,@form1KeyDown));
	form1.OnClose:=toneventaccept(makemethod(nil,@form1Close));

	{init listbox}
	list1:=newlistbox(form1,[loNoExtendSel]);
	list1.SetPosition(5,5);
	list1.Font.FontHeight:=12;
	list1.OnChange:=tonevent(makemethod(nil,@list1Change));
	list1.OnKeyDown:=tonkey(makemethod(nil,@list1KeyDown));

	{init editbox}
	edit1:=neweditbox(form1,[]);
	edit1.SetSize(120,20);
	edit1.Color:=$ffffff;
	edit1.Font.FontHeight:=12;
	edit1.Enabled:=false;
	edit1.OnKeyDown:=tonkey(makemethod(nil,@edit1KeyDown));

	{init groupbox}
	group1[0]:=newgroupbox(form1,'Cookie');
	group1[1]:=newgroupbox(form1,'Image');
	group1[2]:=newgroupbox(form1,'Popup');
	for a:=0to 2do begin
		group1[a].SetSize(120,90);
	end;

	{init radiobox}
	for a:=0to 2do begin
		radio1[a,0]:=newradiobox(group1[a],'Unspecified');
		radio1[a,1]:=newradiobox(group1[a],'Disable');
		radio1[a,2]:=newradiobox(group1[a],'Enable');
		for b:=0to 2do begin
			radio1[a,b].SetSize(100,20);
			radio1[a,b].SetPosition(10,20+b*20);
			radio1[a,b].OnClick:=tonevent(makemethod(nil,@radio1Click));
			radio1[a,b].OnKeyDown:=tonkey(makemethod(nil,@form1KeyDown));
		end;
	end;

	{detect currentdir}
	datpath:=paramstr(0);
	for a:=length(datpath)downto 1do
		if datpath[a]='\'then begin
			datpath:=copy(datpath,1,a)+'cookperm_edit.dat';
			break;
		end;

	{read cookperm location}
	assignfile(f,datpath);
	{$I-}
	reset(f);
	{$I+}
	if IOResult=2then begin
		messagebox(form1.Handle,'cookperm_edit.dat not found.','Error',MB_ICONSTOP);
		halt;
	end;
	readln(f,fpath);
	close(f);
	fpath:=fpath+'\cookperm.txt';

	{read & process cookperm}
	assignfile(f,fpath);
	{$I-}
	reset(f);
	{$I+}
	if IOResult=2then
		messagebox(form1.Handle,pchar(fpath+' not found.'),'Error',MB_ICONSTOP);
	nodata:=false;
	repeat
		readln(f,s);
		if eof(f)then begin nodata:=true;break;end;
	until(s<>'')and(s[1]<>'#')and(s[1]<>'%');
	n:=0;
	repeat
		if nodata then break;
		inc(n);
		setlength(data,n*sizeof(permdata));
		if n>1then readln(f,s);
		data[n].site:=copy(s,1,pos('	',s)-1);
		list1.Add(data[n].site); {site}
		repeat
			s:=copy(s,pos('	',s)+1,length(s)); {permission settings}
			case s[2]of
				'T':data[n].perm[ord(s[1])-ord('0')]:=2;
				'F':data[n].perm[ord(s[1])-ord('0')]:=1;
			end;
		until length(s)=2;
	until eof(f);
	close(f);

	{init listbox selection}
	if list1.Count>0then list1.CurIndex:=0; {select first entry}
	list1Change; {sync}

	run(form1);
end.

{
Changelog
0.1.3 (20040307)
	+ "cookperm_edit.dat not found"
	* "...\cookperm.txt not found"
	* Keyboard navigation now possible with Tab key
0.1.2 (20040303)
	* Handle empty list correctly
0.1.1 (20040302)
	+ "File not found" error message
	* Removed the remaining pchar conversion
	* Handle files with no data correctly
	* Uses KOL 1.91
0.1.0 (20040215)
	+ Edit site name
	+ Add entry
	+ Delete entry
0.0.3 (20040213)
	* Fixed bug when header is < 8 lines
	* Uses string instead of pchar for site name
	* Fixed bug when all is unspecified (now deletes the entry)
0.0.2 (20040209)
	+ About box
	* Listbox size follows window size
	* Uses dynamic arrays for data
0.0.1 (20040208)
	+ Basic navigation: listbox, comboboxes
	+ Basic functionality: edit existing entries
	+ Uses KOL 1.90
20040201
	Started project
}
