program Video;		{ Englische NTSC-Version }

{$I "include:Exec/Ports.i"}
{$I "include:Intuition/Intuition.i"}
{$I "include:Utils/CRT.i"}
{$I "include:Utils/StringLib.i"}
{$I "include:Utils/TimerUtils.i"}
{$I "include:Utils/DateTools.i"}
{$I-}

const
    line="________________________________________________________________________________";
    space="                                                                                ";
    fkey:array[1..10]of string=(	{ Immer 41 Zeichen incl. 0-Byte! }
	"Action\0                                  ",
	"Crime\0                                   ",
	"Comedy\0                                  ",
	"Fantasy\0                                 ",
	"Horror\0                                  ",
	"Science Fiction\0                         ",
	"Cartoon\0                                 ",
	"Adventure\0                               ",
	"Sports\0                                  ",
	"Musics\0                                  ");
    StdInName:String=NIL;
    StdOutName:String=NIL;

type t_eintrag=record
	titel,komment,nummer:string;
	laenge:short;
	next,prev:^t_eintrag
    end;
    t_video=^t_eintrag;
    t_erlaubt=(ALLES,ZAHLEN,BUCHST);

var w:WindowPtr;
    ConBuf:Address;
    last,cass:t_video;
    anzahl:short;
    saved:boolean;
    timer:TimeRequestPtr;
    suchnum,suchstr:string;

function OpenTheWindow:Boolean;
var nw:NewWindowPtr;
begin
    new(nw);
    with nw^ do begin
	LeftEdge:=0; TopEdge:=0; Width:=640; Height:=200;
	DetailPen:=-1; BlockPen:=-1; IDCMPFlags:=0;
	Flags:=WINDOWSIZING+WINDOWDRAG+WINDOWDEPTH+SMART_REFRESH+ACTIVATE;
	FirstGadget:=nil; CheckMark:=nil;
	Title:=" Video-Tape-Archiver  V1.3  ·  © 92-95 by Henning Peters ";
	Screen:=Nil; BitMap:=nil;
	MinWidth:=640; MaxWidth:=-1; MinHeight:=200; MaxHeight:=-1;
	WType:=WBENCHSCREEN_f;
    end;
    w:=OpenWindow(nw); dispose(nw);
    OpenTheWindow:=w<>nil;
end;

procedure WriteChar(c:char);
var s:string;
begin
    s:=AllocString(2); s[1]:='\0'; s[0]:=c; WriteString(conbuf,s)
end;

function str_int(str:string):integer;
var i,j:integer;
begin
    i:=0;
    for j:=0 to pred(strlen(str)) do i:=i*10+ord(str[j])-48;
    str_int:=i
end;

function int_str(i:integer):string;	{ i=0..9999 }
var str:string;
begin str:=AllocString(5); strcpy(str,"\0\0\0\0\0");
    if i<10 then str[0]:=chr(i+48)
    else if i<100 then begin
	str[0]:=chr(i div 10+48); str[1]:=chr(i mod 10+48)
    end else if i<999 then begin
	str[0]:=chr(i div 100+48); str[1]:=chr((i mod 100)div 10+48);
	str[2]:=chr(i mod 10+48)
    end else begin
	str[0]:=chr(i div 1000+48); str[1]:=chr((i mod 1000)div 100+48);
	str[2]:=chr((i mod 100)div 10+48); str[3]:=chr(i mod 10+48)
    end;
    int_str:=str
end;

function lowercase(str:string):string;
var s:string;
    i,j:integer;
begin
    s:=strdup(str); j:=pred(strlen(s));
    for i:=0 to j do s[i]:=tolower(s[i]);
    lowercase:=s
end;

function strpart(s:string; p,l:short):string;
var str:string;
    i:integer;
    e:byte;
begin
    str:=AllocString(succ(l)); e:=pred(p+l);
    for i:=p to e do str[i-p]:=s[i];
    str[succ(l)]:='\0'; strpart:=str
end;

function ja_nein:boolean;
var c:char;
begin
    repeat c:=tolower(readkey(conbuf)) until (c='y') or (c='n') or (c='\e');
    if c='\e' then c:='n'; WriteChar(c); ja_nein:=(c='y')
end;

function stringlen(str:string):byte;
var i:byte;
begin
    i:=pred(strlen(str));
    while (str[i]='_') and (i>-1) do dec(i);
    stringlen:=succ(i)
end;

function GetString(vorgabe:string; len:byte; erlaubt:t_erlaubt):string;
var l,x,y,b,pos,slen:byte;
    str,s1,s2:string;
    c:char;
    i:integer;
    ok:boolean;
begin
    x:=succ(wherex(conbuf)); y:=succ(wherey(conbuf));
	{ Scheint so, als wenn where_=[0..max-1] und gotoxy=[1..max] }
    str:=AllocString(succ(len)); slen:=strlen(vorgabe); pos:=0;
    strcpy(str,vorgabe); if slen<len then strncat(str,line,len-slen); s1:=strdup(str);
    GotoXY(conbuf,x,y); WriteString(conbuf,str); GotoXY(conbuf,x,y);
    repeat
	c:=readkey(conbuf); b:=ord(c);
	if (erlaubt=ALLES) or (erlaubt=BUCHST) then ok:=((b>31) and (b<127)) or (b>160)
	else ok:=(b>47) and (b<58); { Nur '0'..'9' }
	if ok then begin
	    if (pos=slen) and (slen<len) then begin
		str[pos]:=c; GotoXY(conbuf,x+pos,y); WriteChar(c)
	    end else if (slen<len) then begin
		    for i:=pred(slen) downto pos do str[succ(i)]:=str[i];
		    str[pos]:=c;
		    GotoXY(conbuf,x,y); WriteString(conbuf,str); GotoXY(conbuf,x+pos,y)
		end else if pos<len then str[pos]:=c;
	    if (slen<len) then begin inc(slen); inc(pos) end
	end else begin
	    case b of
	      155:begin
		    c:=readkey(conbuf);
		    case ord(c) of
			65:pos:=0;
			66:pos:=slen;
			67:if pos<slen then inc(pos);
			68:if pos>0 then dec(pos);
			63:if erlaubt=ALLES then begin	{ Help }
			    WriteString(conbuf,"\n\n");
			    for i:=1 to 10 do begin
				WriteChar('\t'); WriteString(conbuf,fkey[i]);
				WriteChar('\n') end;
			    y:=wherey(conbuf)-11;
			    GotoXY(conbuf,0,succ(y));
WriteString(conbuf,"\n\e[4m\e[41m\e[30m F1  \n F2  \n F3  \n F4  \n F5  \n F6  \n F7  \n F8  \n F9  \n F10 \e[0m");
			    GotoXY(conbuf,x,y)
			end;
			48..57:if (erlaubt=ALLES) and
				(strlen(fkey[ord(c)-47])+pos<=len) then begin { F-Tasten }
			    b:=ord(c)-47; s2:=fkey[b]; l:=strlen(s2); 
			    if slen>0 then for i:=slen downto pos do str[i+l]:=str[i];
			    for i:=0 to pred(l) do str[pos+i]:=s2[i];
			    inc(slen,l); inc(pos,l); ok:=true
			end
		    end;
		    while keypressed(conbuf) do c:=readkey(conbuf);
		end;	{ Fuer '~' am Ende, Shift-F-Tasten etc. }
	      27:begin s2:=str; str:=s1; s1:=s2; ok:=true; slen:=stringlen(str);
			 pos:=slen end;
	      160:begin s2:=str; str:=s1; s1:=s2; ok:=true;
			 strncpy(str,line,len); slen:=0; pos:=0 end;
	      8:if pos>0 then begin
		    dec(slen); for i:=pos to slen do str[pred(i)]:=str[i];
		    str[slen]:='_'; dec(pos); ok:=true
		end;
	      127:if pos<slen then begin
		    if pos<pred(slen) then
			for i:=pos to pred(slen) do str[i]:=str[succ(i)];
		    dec(slen); str[slen]:='_'; ok:=true;
		    if (pos=slen) and (pos>0) then dec(pos)
		end
	    end;
	    if ok then begin GotoXY(conbuf,x,y); WriteString(conbuf,str) end
	end;
	GotoXY(conbuf,x+pos,y)
    until b=13;
    if slen=0 then begin if erlaubt=ZAHLEN then str[0]:='0' else str[0]:=' '; slen:=1 end;
    strncpy(str,str,slen); strcpy(s1,str); if slen<len then strncat(s1,space,len-slen);
    GotoXY(conbuf,x,y); WriteString(conbuf,s1); GetString:=str
end;

procedure funktionstasten;
var i:integer;
    s:string;
    c1,c2:char;
begin
    WriteString(conbuf,"\f		\e[42m Change functionkeytexts \e[0m\n\n");
WriteString(conbuf,"\e[4m\e[41m\e[30m F1  \n F2  \n F3  \n F4  \n F5  \n F6  \n F7  \n F8  \n F9  \n F10 \e[0m");
    for i:=1 to 10 do begin GotoXY(conbuf,8,2+i); WriteString(conbuf,fkey[i]) end;
    WriteString(conbuf,"\n\n\e[41m\e[30m Esc \e[0m	Abort\n\n	Change which key? ");
    repeat
	repeat
	    repeat c1:=readkey(conbuf) until (c1='\c') or (c1='\e');
	    if c1='\e' then return;
	    c2:=readkey(conbuf);
	until (c2>'/') and (c2<':');
	c1:=readkey(conbuf); if c1<'~' then begin c2:=c1; c1:=readkey(conbuf) end;
	i:=ord(c2)-47; GotoXY(conbuf,8,2+i); CursOn(conbuf);
	s:=GetString(fkey[i],40,ALLES); CursOff(conbuf);
	strcpy(fkey[i],s)
    until false
end;

procedure einsort(neu:t_video);
var c:t_video;
begin
    if cass=nil then begin
	neu^.next:=neu; neu^.prev:=neu; cass:=neu; last:=neu
    end else begin
	c:=cass;
	while (stricmp(neu^.titel,c^.titel)>0) and (c<>last) do c:=c^.next;
	if (c=last) and (stricmp(neu^.titel,c^.titel)>0) then c:=cass;
	neu^.next:=c; neu^.prev:=c^.prev; c^.prev^.next:=neu; c^.prev:=neu;
	if (c=cass) then
	    if (stricmp(neu^.titel,cass^.titel)<0) then cass:=neu
	    else last:=neu
    end; inc(anzahl);
end;

procedure ausklinken(var v:t_video);
var d:t_video;
begin
    v^.prev^.next:=v^.next; v^.next^.prev:=v^.prev; d:=v; v:=v^.next;
    dispose(d); saved:=false; dec(anzahl);
end;

procedure eingabe(a,b,c,d:string; var t,k,l,n:string);
begin
    WriteChar('\n'); InsLine(conbuf); InsLine(conbuf);
    WriteString(conbuf,"\nTitle  : "); t:=strdup(GetString(a,60,ALLES));
    WriteChar('\n'); InsLine(conbuf);
    WriteString(conbuf,"Comment: "); k:=strdup(GetString(b,60,ALLES));
    WriteChar('\n'); InsLine(conbuf); WriteString(conbuf,"Length :     min");
    GotoXY(conbuf,wherex(conbuf)-6,succ(wherey(conbuf)));
    l:=strdup(GetString(c,3,ZAHLEN)); WriteChar('\n'); InsLine(conbuf);
    WriteString(conbuf,"Number : "); n:=strdup(GetString(d,3,BUCHST));
    saved:=false
end;

procedure eingeben;
var neu:t_video;
    c:char;
    t,k,l,n:string;
begin
    WriteString(conbuf,"\f		\e[42m Enter new title \e[0m");
    repeat
	new(neu); eingabe("","","","",t,k,l,n);
	neu^.titel:=t; neu^.komment:=k;
	neu^.laenge:=str_int(l); neu^.nummer:=n;
	einsort(neu); WriteChar('\n'); InsLine(conbuf); InsLine(conbuf);
	WriteString(conbuf,"\n	Another one (y/n)? ");
    until not ja_nein
end;

procedure ausgabe(v:t_video);
begin
    WriteString(conbuf,"\n\n\e[2mTitle  : \e[0m");
    WriteString(conbuf,v^.titel);
    WriteString(conbuf,"\n\e[2mComment: \e[0m");
    WriteString(conbuf,v^.komment);
    WriteString(conbuf,"\n\e[2mLength : \e[0m");
    WriteString(conbuf,int_str(v^.laenge));
    WriteString(conbuf," min	\e[2mNumber: \e[0m");
    WriteString(conbuf,v^.nummer)
end;

procedure ansehen;
var v:t_video;
    c:byte;
begin
    WriteString(conbuf,"\e[0 p\f		\e[42m Show all title \e[0m");
    v:=cass;
    repeat
	ausgabe(v);
	WriteString(conbuf,
"\n\n	\e[42m       \e[0m=Forward, \e[42m Esc \e[0m=Abort, \e[42m ^ \e[0m=Backward");
	repeat
	    c:=ord(readkey(conbuf));
	    if c=155 then c:=ord(readkey(conbuf))
	until (c=65) or (c=32) or (c=27);
	case c of
	    65:v:=v^.prev;
	    32:v:=v^.next
	end
    until c=27
end;

function such_text(wie:char; v:t_video):t_video;
var l:byte;
    q,p:integer;
    s:string;
begin
    l:=strlen(suchstr); s:=lowercase(suchstr); FreeString(suchstr); suchstr:=s;
    repeat
	if wie='k' then s:=lowercase(v^.komment) else s:=lowercase(v^.titel);
	p:=strlen(s)-l;
	if p>0 then for q:=0 to p do
	    if s[q]=suchstr[0] then
		if strieq(strpart(s,q,l),suchstr) then such_text:=v;
	v:=v^.next;
    until v=cass;
    such_text:=nil
end;

function such_nummer(v:t_video):t_video;
begin
    repeat
	if strcmp(suchnum,v^.nummer)=0 then such_nummer:=v;
	v:=v^.next
    until v=cass;
    such_nummer:=nil
end;
    
function such_video(var c:char):t_video;
begin
    WriteString(conbuf,
"\n\nSearch for a \e[42m t \e[0mitle, \e[42m c \e[0momment, or \e[42m n \e[0mumber? ");
    repeat c:=tolower(readkey(conbuf)) until (c='t') or (c='c') or (c='n');
    WriteChar(toupper(c));
    if (c='c') or (c='t') then begin
	WriteString(conbuf,"\nSearch for: "); suchstr:=strdup(GetString("",60,ALLES));
	such_video:=such_text(c,cass)
    end else begin
	WriteString(conbuf,"\nSearch number: "); suchnum:=strdup(GetString("",3,BUCHST));
	such_video:=such_nummer(cass)
    end
end;

procedure aendern;
var v,d:t_video;
    c:char;
    str,l,n:string;
    num:byte;
    jn:boolean;
begin
    WriteString(conbuf,"\f		\e[42m Change title \e[0m");
    repeat
	v:=such_video(c); jn:=true;
	if v<>nil then repeat
	    ausgabe(v);
	    WriteString(conbuf,"\n\n	\e[33mChange\e[0m this title (y/n)? ");
	    if ja_nein then begin
		l:=int_str(v^.laenge); n:=v^.nummer;
		eingabe(v^.titel,v^.komment,l,n,v^.titel,v^.komment,l,n);
		new(d); d^.titel:=v^.titel; d^.komment:=v^.komment;
		d^.laenge:=str_int(l); d^.nummer:=n;
		ausklinken(v); einsort(d)	{ Neu einsortieren }
	    end;
	    WriteString(conbuf,"\n\n	Search next title (y/n)? ");
	    jn:=ja_nein;
	    if jn then if (c='t') or (c='c') then v:=such_text(c,v^.next)
			else v:=such_nummer(v^.next)
	until (not jn) or (v=nil);
	if v=nil then WriteString(conbuf,"\n\n	No such title found!");
	WriteString(conbuf,"\n\n	Search another one (y/n)? ");
	jn:=ja_nein
    until not jn
end;

procedure suchen;
var v:t_video;
    c:char;
    str,l,n:string;
    num:byte;
    jn:boolean;
begin
    WriteString(conbuf,"\f		\e[42m Search title \e[0m");
    repeat
	v:=such_video(c); jn:=true;
	if v<>nil then repeat
	    ausgabe(v);
	    WriteString(conbuf,"\n\n	Search next title (y/n)? ");
	    jn:=ja_nein;
	    if jn then if (c='t') or (c='c') then v:=such_text(c,v^.next)
			else v:=such_nummer(v^.next)
	  until (not jn) or (v=nil);
	if v=nil then WriteString(conbuf,"\n\n	So such title found!");
	WriteString(conbuf,"\n\n	Search another one (y/n)? ");
	jn:=ja_nein
    until not jn
end;

procedure loeschen;
var v:t_video;
    c:char;
    str:string;
    num:byte;
    jn:boolean;
begin
    WriteString(conbuf,"\f		\e[42m Delete title \e[0m");
    repeat
	v:=such_video(c);
	if v<>nil then repeat
	    ausgabe(v);
	    WriteString(conbuf,"\n\n	\e[33mDelete\e[0m this title (y/n)? ");
	    if ja_nein then ausklinken(v);
	    WriteString(conbuf,"\n\n		Title deleted .\n\n	Search next one (y/n)? ");
	    jn:=ja_nein;
	    if jn then if (c='t') or (c='c') then v:=such_text(c,v^.next)
			else v:=such_nummer(v^.next)
	until (not jn) or (v=nil);
	if v=nil then WriteString(conbuf,"\n\n	No such title found!");
	WriteString(conbuf,"\n\n	Search another one (y/n)? ");
	jn:=ja_nein
    until not jn
end;

procedure IO_error(txt:string; err:byte);
var s:string;
begin
    case err of
	50:s:="No memory for IO-buffer";
	103:s:="Insufficient free memory";
	202:s:="File in use";
	203:s:="File already exists";
	204:s:="Directory not found";
	205:s:="File not found";
	213:s:="Disk not validated";
	214:s:="Disk is write protected";
	218:s:="Device not mounted";
	221:s:="Disk is full";
	223:s:="File is write protected";
	223:s:="File is read protected";
	225:s:="Not a DOS-Disk";
	226:s:="No Disk in drive";
	else begin
	    s:=AllocString(20); strcpy(s,"Error number "); strcat(s,int_str(err))
	end
    end;
    WriteString(conbuf,"\n\n\a	\e[33mError\e[0m while ");
    WriteString(conbuf,txt); WriteString(conbuf,s);
    WriteString(conbuf,".\n\n		Press any key to continue ");
    while not keypressed(conbuf) do
end;

procedure speichern;
var v:t_video;
    f:text;
    s:string;
    err:byte;
    over:boolean;
    i:integer;
begin
    WriteString(conbuf,
	"\f		\e[42m Save titles \e[0m\n\nFilename (full path):\n");
    s:=strdup(GetString("Video-Archive",75,ALLES));
    reset(f,s); err:=ioresult; close(f);
    if err=0 then begin
	WriteString(conbuf,"\n\n\a	File already exists! \e[33mOverwrite\e[0m (y/n)? ");
	over:=ja_nein; if not over then return
    end;
    WriteString(conbuf,"\n\nWriting Data");
    rewrite(f,s); err:=ioresult;
    if not ((err=203) and over) then if err>0 then begin
	if over then io_error("overwriting old file: ",err)
	else io_error("opening the file: ",err); close(f); return
    end;
    v:=cass; i:=1; err:=0;
    while (err=0) and (i<11) do begin writeln(f,fkey[i]); err:=ioresult; inc(i) end;
    if err>0 then begin io_error("writing: ",err); close(f); return end;
    repeat
	writeln(f,v^.titel,"\n",v^.komment,"\n",v^.laenge,":",v^.nummer);
	err:=ioresult; WriteChar('.');
	if err>0 then begin io_error("writing: ",err); close(f); return end;
	v:=v^.next
    until v=cass;
    close(f); err:=ioresult;
    if err>0 then io_error("closing the file: ",err)
    else begin
	WriteString(conbuf,"Ok."); saved:=true;
	WriteString(conbuf,"\n\n		Press any key to continue ");
	while not keypressed(conbuf) do
    end
end;

procedure laden;
var v:t_video;
    f:text;
    t,k,n:string;
    err:byte;
    l:short;
    i:integer;
    c:char;
begin
    WriteString(conbuf,"\f		\e[42m Load titles \e[0m");
    if not saved then begin
	WriteString(conbuf,"\n\nCurrent data is not saved! \e[33mOverwrite\e[0m (y/n)? ");
	if not ja_nein then return
    end;
    WriteString(conbuf,"\n\nFilename (full path):\n");
    t:=strdup(GetString("Video-Archive",75,ALLES));
    reset(f,t); err:=ioresult;
    if err>0 then begin io_error("opening the file: ",err); close(f); return end;
    if anzahl>0 then				{ Alte Daten löschen }
	if anzahl=1 then dispose(cass)
	else begin
	    v:=cass;
	    repeat ausklinken(v^.prev) until v=v^.next;
	    dispose(v)
	end;
    WriteString(conbuf,"\n\nReading data"); anzahl:=0; cass:=nil; i:=1; err:=0;
    FreeString(t); t:=AllocString(61); k:=AllocString(61); n:=AllocString(4);
    while (err=0) and (i<11) do begin
	readln(f,t); err:=ioresult; if err=0 then strcpy(fkey[i],t); inc(i)
    end;
    if err>0 then begin io_error("reading: ",err); close(f); return end;
    repeat
	readln(f,t); err:=ioresult;
	if err=0 then begin readln(f,k); err:=ioresult end;
	if err=0 then begin readln(f,l,c,n); err:=ioresult end;
	if err>0 then begin io_error("reading: ",err); close(f); return end;
	new(v); v^.titel:=strdup(t); v^.komment:=strdup(k); v^.laenge:=l;
	v^.nummer:=strdup(n); WriteChar('.'); einsort(v)
    until eof(f);
    close(f); WriteString(conbuf,"Ok.\n\n		Press any key to continue ");
    while not keypressed(conbuf) do; saved:=true
end;

procedure drucken;
var drucker:text;
    v:t_video;
    c:byte;
begin
  WriteString(ConBuf,"\e[0 p\f	\e[42m Print titles \e[0m\n\nUse \e[42m Esc \e[0m to abort.\n");
  reset(drucker,"prt:"); c:=ioresult;
  if c>0 then begin
    io_error("opening the printer",c); close(drucker); return
  end;
  v:=cass; c:=0; WriteString(ConBuf,"\nPrinting");
  repeat
    WriteLn(drucker,"\n\e[1mTitel  : \e[0m",v^.titel,"\n\e[1mComment: \e[0m",
	v^.komment,"\n\e[1mLength   : \e[0m",int_str(v^.laenge):4,
	" min      \e[1mNumber: \e[0m",v^.nummer);
    v:=v^.next; WriteChar('.');
    if keypressed(ConBuf) then c:=ord(readkey(ConBuf));
  until (v=cass) or (c=27);
  close(drucker)
end;

function my_menu:char;
var c1,c2:char;
    h,m,s:byte;
    sec,t:integer;
    time:DateDescription;
    tv:timeval;
    str:string;
begin
    str:=AllocString(42);
    WriteString(conbuf,"\e[0 p\f\n		\e[42m M a i n m e n u \e[0m\n\n");
    WriteString(conbuf,"    \e[30;4;41m F1  \e[0m Enter new title\n");
    WriteString(conbuf,"    \e[30;4;41m F2  \e[0m Show all title\n");
    WriteString(conbuf,"    \e[30;4;41m F3  \e[0m Change title\n");
    WriteString(conbuf,"    \e[30;4;41m F4  \e[0m Search title\n");
    WriteString(conbuf,"    \e[30;4;41m F5  \e[0m Delete title\n");
    WriteString(conbuf,"    \e[30;4;41m F6  \e[0m Save titles\n");
    WriteString(conbuf,"    \e[30;4;41m F7  \e[0m Load titles\n");
    WriteString(conbuf,"    \e[30;4;41m F8  \e[0m Print titles\n");
    WriteString(conbuf,"    \e[30;4;41m F9  \e[0m Change functionkeytexts\n");
    WriteString(conbuf,"    \e[30;4;41m F10 \e[0m Exit program\n\n");
    WriteString(conbuf,int_str(anzahl));
    WriteString(conbuf," title in memory");
    if not saved then WriteString(conbuf," (modified)");
    WriteString(conbuf,".");
    repeat sec:=0;
      repeat
	GetSysTime(timer,tv);
	if sec<>tv.tv_secs then begin
	    sec:=tv.tv_secs; t:=sec mod 86400;
	    h:=t div 3600; m:=(t mod 3600)div 60; s:=t mod 60;
	    GetDescription(tv.tv_secs,time);	{ TimeDesc() gibt Müll bei h/m/s }
	    strcpy(str," "); strcat(str,DayNames[time.dow]); strcat(str,", ");
	    strcat(str,int_str(time.day)); strcat(str,".");
	    strcat(str,int_str(time.month)); strcat(str,".");
	    strcat(str,int_str(time.year)); strcat(str,", ");
	    strcat(str,int_str(h)); strcat(str,":");
	    if m<10 then strcat(str,"0"); strcat(str,int_str(m)); strcat(str,":");
	    if s<10 then strcat(str,"0"); strcat(str,int_str(s));
	    GotoXY(conbuf,MaxX(conbuf)-strlen(str),1); WriteString(conbuf,str)
	end;
	if keypressed(conbuf) then c1:=readkey(conbuf)
      until c1='\c';
      c2:=readkey(conbuf)
    until (c2>'/') and (c2<':');	{ F-Tasten='<CSI>[0..9]~' }
    c1:=readkey(conbuf); if c1<'~' then begin c2:=c1; c1:=readkey(conbuf) end;
    CursOn(conbuf);			{ Shift-Fxx='<CSI>1[0..9]~' }
    case c2 of
	'0':eingeben;
	'1':if anzahl>0 then ansehen;
	'2':if anzahl>0 then aendern;
	'3':if anzahl>0 then suchen;
	'4':if anzahl>0 then loeschen;
	'5':if anzahl>0 then speichern;
	'6':laden;
	'7':if anzahl>0 then drucken;
	'8':funktionstasten;
	'9':begin
	      GotoXY(conbuf,15,17);
	      if not saved then WriteString(conbuf,"\e[33mTitles are modified! \e[0m");
	      WriteString(conbuf,"\e[43m Really leave (y/n)?\e[0m");
	      if ja_nein then c2:='\0';
	   end
    end;
    my_menu:=c2
end;

begin	{ Main }
    if OpenTheWindow then begin
	ConBuf:=AttachConsole(w);
	if ConBuf<>Nil then begin
	    timer:=CreateTimer;
	    if timer<>nil then begin
		cass:=nil; anzahl:=0; saved:=true;
		while my_menu>'\0' do;
		DetachConsole(ConBuf); DeleteTimer(timer)
	    end else writeln("\aUnable to open \e[33mtimer.device\e[0m!")
	end else writeln("\aUnable to open \e[33mconsole.device\e[0m!");
	CloseWindow(w)
    end else writeln("\aUnable to open \e[33mwindow\e[0m!")
end.
