3 #=======================================================================
5 # File ID: c1080bc6-f742-11dd-acb1-000475e441b9
6 # Ny versjon av DBK-systemet.
9 # ©opyleft 1999– Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later, see end of
11 # file for legal stuff.
12 #=======================================================================
38 $progname =~ s/^.*\/(.*?)$/$1/;
39 our $VERSION = '0.1.0';
41 Getopt
::Long
::Configure
('bundling');
44 'batch|b' => \
$Opt{'batch'},
45 'force|f' => \
$Opt{'force'},
46 'help|h' => \
$Opt{'help'},
47 'insert-file|i=s' => \
$Opt{'insert-file'},
48 'now|t' => \
$Opt{'now'},
49 'quiet|q+' => \
$Opt{'quiet'},
50 'verbose|v+' => \
$Opt{'verbose'},
51 'version' => \
$Opt{'version'},
52 'zone|z' => \
$Opt{'zone'},
54 ) || die("$progname: Option error. Use -h for help.\n");
56 $Opt{'verbose'} -= $Opt{'quiet'};
57 $Opt{'help'} && usage
(0);
58 if ($Opt{'version'}) {
64 my $dbk_dir = "$ENV{HOME}/dbk";
65 my $Viewer = "lynx -assume_charset=UTF-8 -homepage=file://$dbk_dir";
66 my $dbk_ext = ".html";
67 my $dbk_lockext = ".lock";
71 my $time_not_found = 0;
72 my @day_name = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
74 msg
(3, "$0: \$Opt{'now'} = $Opt{'now'}");
76 my ($Sec, $Min, $Hour, $Day, $Mon, $Year, $Wday, $Yday, $is_dst)
77 = localtime($curr_time);
82 msg
(3, "\$curr_time: $Year-$Mon-$Day $Hour:$Min:$Sec, " .
83 "\$Wday = $Wday, \$Yday = $Yday, \$is_dst = $is_dst");
85 # Parameterparsing og initialisering av datovariabler {{{
87 my $time_str = ""; # Strengen som det vil bli leita etter og som blir satt inn.
90 /^\d\d:/ && (splice(@ARGV, $arg_count, 1),
96 $Year = $ARGV[2] if $#ARGV >= 2;
97 $Mon = sprintf("%02u", $ARGV[1]) if $#ARGV >= 1;
98 $Day = sprintf("%02u", $ARGV[0]) if $#ARGV >= 0;
100 # Når vi nærmer oss 2030 begynner dette å bli en fixme. :)
103 } elsif ($Year < 100) {
107 $Mon =~ s/^(\d)$/0$1/;
108 $Day =~ s/^(\d)$/0$1/;
109 $Hour =~ s/^(\d)$/0$1/;
110 $Min =~ s/^(\d)$/0$1/;
111 $Sec =~ s/^(\d)$/0$1/;
113 die("$0: $Day: Feil format på datoen\n") unless ($Day =~ /^\d\d$/);
114 die("$0: $Mon: Feil format på måneden\n") unless ($Mon =~ /^\d\d$/);
115 die("$0: $Year: Feil format på året\n") unless ($Year =~ /^\d\d\d\d$/);
117 my $time_utc = timegm
($Sec, $Min, $Hour, $Day, $Mon-1, $Year);
118 my $time_sec = timelocal
($Sec, $Min, $Hour, $Day, $Mon-1, $Year);
119 my @time_arr = localtime($time_sec);
120 my $week_day = $time_arr[6];
121 my $utc_diff = ($time_utc-$time_sec)/3600;
123 msg
(3, "Etter ARGV: $Year-$Mon-$Day");
124 msg
(3, "\$dbk_dir = $dbk_dir");
125 msg
(3, "\$Opt{'insert-file'} = \"$Opt{'insert-file'}\"");
128 # Sjekk at alle katalogene er på plass {{{
129 my $year_dir = "$dbk_dir/$Year";
130 my $dbk_file = "$year_dir/${Year}${Mon}${Day}${dbk_ext}";
131 my $lock_dir = "$year_dir/${Year}${Mon}${Day}${dbk_lockext}";
134 unless (-d
$dbk_dir) {
135 mkdir($dbk_dir, $dir_mode)
136 || die("$0: $dbk_dir: Kan ikke lage directoryen: $!\n");
138 unless (-d
$year_dir) {
139 mkdir($year_dir, $dir_mode)
140 || die("$0: $year_dir: Kan ikke lage directoryen: $!\n");
143 msg
(3, "\$dbk_file = $dbk_file");
146 rmdir($lock_dir) || warn("$0: $lock_dir: " .
147 "Kan ikke fjerne gammel lockdir med makt: $!\n");
154 until (mkdir($lock_dir, 0777)) {
155 $print_ok || print(STDERR
"Venter på at lockdir $lock_dir " .
156 "skal forsvinne ($!)..");
161 $print_ok && print("OK\n");
164 open(CheckFP
, ">$year_dir/.check")
165 || die("$0: $year_dir/.check: Klarte ikke å lage fila: $!\n");
167 unlink("$year_dir/.check")
168 || die("$0: $year_dir/.check: Cannot delete file, aborting");
170 unless (-f
$dbk_file) {
171 open(FP
, ">$dbk_file")
172 || die("$0: $dbk_file: Kan ikke åpne fila for skriving: $!\n");
173 print(FP
"<h1>$day_name[$week_day] $Year-$Mon-$Day</h1>\n")
174 || die("$0: $dbk_file: Kan ikke skrive header til fila: $!\n");
178 my $min_size = 0; # Minimum size of file to prevent deletion
181 # Legg til klokkeslettet akkurat nå i fila og gå inn i editoren {{{
182 my $utc_str = sprintf("%s%02u00", $utc_diff < 0 ?
"-" : "+", $utc_diff);
183 $utc_str = "" unless $Opt{'zone'};
184 if (length($time_str)) {
185 $time_str .= $utc_str;
187 $time_str = "$Hour:$Min:$Sec$utc_str";
189 open(dbkFP
, "+<$dbk_file")
190 || die("$0: $dbk_file: " .
191 "Kan ikke åpne fila for lesing+skriving+flock: $!\n");
192 flock(dbkFP
, LOCK_EX
)
193 || die("$0: $dbk_file: Klarte ikke flock(): $!\n");
194 my $which_line = find_line
($time_str);
195 if ($time_not_found) {
197 || die("$0: $dbk_file: Klarte ikke å seeke " .
198 "til slutten for å legge til LF: $!\n");
200 || warn("$0: $dbk_file: Feil under skriving til fila: $!\n");
203 length($Opt{'insert-file'})
204 ? insert_file
($Opt{'insert-file'}, $which_line)
205 : insert_time
($time_str, $which_line);
208 system("$Editor +$which_line $dbk_file") unless
209 (length($Opt{'insert-file'}) || length($Opt{'batch'}));
216 unless ($Opt{'batch'}) {
217 system("$Viewer $dbk_file");
221 my @stat_info = stat($dbk_file);
222 my $file_size = $stat_info[7];
223 if ($file_size < $min_size) {
224 print("Ingenting ble skrevet, så jeg sletter driten.\n");
226 || warn("$0: $dbk_file: Klarte ikke å slette fila: $!\n");
230 rmdir($lock_dir) || die("$0: $lock_dir: Klarte ikke å slette lockdir: $!\n");
237 my $srch_time = shift;
241 || die("$dbk_file: Klarte ikke å gå til begynnelsen av fila: $!\n");
243 if (/^<p><b>(\d\d:\d\d:\d\d)/i || /^<p><b>(\d\d:\d\d)/i) {
245 return($.) if ($srch_time lt $found_time);
255 my ($time_str, $line_num) = @_;
257 || die("$dbk_file: Klarte ikke å gå " .
258 "til begynnelsen av fila i insert_time(): $!\n");
259 my @Linjer = <dbkFP
>;
264 sprintf("<p><b>$time_str</b> -\n%s", $time_not_found ?
"" : "\n")
267 || die("$0: $dbk_file: Klarte ikke å seeke til starten " .
268 "i insert_time(): $!\n");
270 || die("$0: $dbk_file: Klarte ikke å trunce fila til 0: $!\n");
273 || warn("$0: $dbk_file: Å neiiii, katastrofe! " .
274 "Feil under skriving til fila: $!\n");
280 # Sjekker om en tekst inneholder ulovlige UTF-8-sekvenser og
281 # returnerer i så fall 0
285 # Henta fra "find_inv_utf8,v 1.1 2001/09/07 08:54:31 sunny" og
286 # modifisert litt. FIXME: Klager ikke på overlange sekvenser og tegn
287 # i UTF-16-surrogatområdet
288 $Str =~ s
/([\xFC-\xFD][\x80-\xBF][\x80-\xBF]
289 [\x80-\xBF][\x80-\xBF][\x80-\xBF])//gx;
290 $Str =~ s/([\xF8-\xFB][\x80-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF])//g;
291 $Str =~ s/([\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])//g;
292 $Str =~ s/([\xE0-\xEF][\x80-\xBF][\x80-\xBF])//g;
293 $Str =~ s/([\xC0-\xDF][\x80-\xBF])//g;
294 $Retval = 0 if ($Str =~ /[\x80-\xFD]/);
295 msg
(3, "is_utf8() returnerer $Retval.");
302 my ($file_name, $line_num) = @_;
305 || die("$0: $dbk_file: Klarte ikke å gå til begynnelsen av fila " .
306 "i insert_file(): $!\n");
307 my @Linjer = <dbkFP
>;
308 my @InsLinj = "<p><b>$time_str</b> -\n";
309 open(LocFP
, "<$file_name")
310 || die("$0: $file_name: Kan ikke åpne fila for lesing: $!\n");
311 push(@InsLinj, <LocFP
>);
312 push(@InsLinj, "\n") unless $time_not_found; # Denne likte jeg egentlig
313 # fantastisk dårlig, men hvem
314 # bruker vel å ha to LF’er på
317 msg
(3, "\$_ = \"$_\"");
319 warn("$0: Ugyldig UTF-8 funnet, " .
320 "behandler teksten som ISO-8859-1.\n");
322 for my $Curr (@InsLinj) {
323 msg
(3, "FØR : \$Curr = \"$Curr\"");
324 $Curr =~ s/([\x80-\xFF])/widechar(ord($1))/ge;
325 msg
(3, "ETTER: \$Curr = \"$Curr\"");
332 splice(@Linjer, $line_num-1, 0, @InsLinj);
335 || die("$0: $dbk_file: Klarte ikke å seeke til starten " .
336 "i insert_file(): $!\n");
338 || die("$0: $dbk_file: Klarte ikke å trunce fila til 0: $!\n");
339 msg
(3, "scalar(\@Linjer): \"" . scalar(@Linjer) . "\".");
340 foreach my $Curr (@Linjer) {
341 $Curr =~ s/&#(\d{1,10});/widechar($1)/ge;
342 $Curr =~ s/&#x([0-9a-f]{1,8});/widechar(hex($1))/gei;
344 || warn("$0: $dbk_file: Knallkrise. " .
345 "Feil under skriving til fila: $!\n");
351 # Print program version {{{
352 print("$progname $VERSION\n");
358 # Send the help message to stdout {{{
361 if ($Opt{'verbose'}) {
367 Syntax: $progname [valg] [dag [måned [år]]] [HH:MM]
372 Batch mode, ikke start editor eller viewer.
374 Force, start dbk selv om lockdir eksisterer.
377 -i x, --insert-file x
378 Sett inn filen x istedenfor å bruke tastatur. Forventer -t eller
381 Be more quiet. Can be repeated to increase silence.
383 Legg til klokkeslettet akkurat nå i fila og gå inn i editoren
385 Increase level of verbosity. Can be repeated.
387 Print version information.
389 Legg til tidssone til klokkeslett
391 Klokkeslettet kan spesifiseres hvor som helst, men må starte med
392 formatet "HH:" der HH er to siffer.
400 # Print a status message to stderr based on verbosity level {{{
401 my ($verbose_level, $Txt) = @_;
403 if ($Opt{'verbose'} >= $verbose_level) {
404 print(STDERR
"$progname: $Txt\n");
411 # Konverterer en tegnverdi til UTF-8 {{{
412 # Henta fra "h2u,v 1.5 2002/11/20 00:09:40 sunny".
414 my $allow_invalid = 0;
417 return sprintf("%c", $Val);
418 } elsif ($Val < 0x800) {
419 return sprintf("%c%c", 0xC0 | ($Val >> 6),
420 0x80 | ($Val & 0x3F));
421 } elsif ($Val < 0x10000) {
422 unless ($allow_invalid) {
423 if (($Val >= 0xD800 && $Val <= 0xDFFF)
425 || ($Val eq 0xFFFF)) {
429 return sprintf("%c%c%c", 0xE0 | ($Val >> 12),
430 0x80 | (($Val >> 6) & 0x3F),
431 0x80 | ($Val & 0x3F));
432 } elsif ($Val < 0x200000) {
433 return sprintf("%c%c%c%c", 0xF0 | ($Val >> 18),
434 0x80 | (($Val >> 12) & 0x3F),
435 0x80 | (($Val >> 6) & 0x3F),
436 0x80 | ($Val & 0x3F));
437 } elsif ($Val < 0x4000000) {
438 return sprintf("%c%c%c%c%c", 0xF8 | ($Val >> 24),
439 0x80 | (($Val >> 18) & 0x3F),
440 0x80 | (($Val >> 12) & 0x3F),
441 0x80 | (($Val >> 6) & 0x3F),
442 0x80 | ( $Val & 0x3F));
443 } elsif ($Val < 0x80000000) {
444 return sprintf("%c%c%c%c%c%c", 0xFC | ($Val >> 30),
445 0x80 | (($Val >> 24) & 0x3F),
446 0x80 | (($Val >> 18) & 0x3F),
447 0x80 | (($Val >> 12) & 0x3F),
448 0x80 | (($Val >> 6) & 0x3F),
449 0x80 | ( $Val & 0x3F));
451 return widechar
(0xFFFD);
458 # This program is free software; you can redistribute it and/or modify
459 # it under the terms of the GNU General Public License as published by
460 # the Free Software Foundation; either version 2 of the License, or (at
461 # your option) any later version.
463 # This program is distributed in the hope that it will be useful, but
464 # WITHOUT ANY WARRANTY; without even the implied warranty of
465 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
466 # See the GNU General Public License for more details.
468 # You should have received a copy of the GNU General Public License
469 # along with this program.
470 # If not, see L<http://www.gnu.org/licenses/>.
472 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :