Change MozEmbed subcommand communications.
[techtalk-pse.git] / techtalk-pse.pl
index 3955c7e..eb5ddd8 100755 (executable)
@@ -191,6 +191,11 @@ if (@ARGV > 0) {
     }
 }
 
+# Get the talk directory and set environment variable $talkdir
+# which is inherited by all the scripts.
+my $talkdir = getcwd;
+$ENV{talkdir} = $talkdir;
+
 # Get the files.
 my @files;
 my %files;
@@ -242,11 +247,7 @@ if ($splash) {
     my $w = Gtk2::AboutDialog->new;
     $w->set_authors ("Richard W.M. Jones");
     $w->set_comments (
-        "Superior technical demonstration software\n".
-        "\n".
-        "Keys\n".
-        "↑ — Go back one slide\n".
-        "↓ — Go forward one slide\n"
+        "Superior technical demonstration software\n"
         );
     $w->set_program_name ("Tech Talk Platinum Supreme Edition (PSE)");
     $w->set_version ("@VERSION@");
@@ -255,6 +256,11 @@ if ($splash) {
     $w->run;
     print STDERR "calling \$w->destroy on about dialog\n" if $verbose;
     $w->destroy;
+
+    # The dialog doesn't really get destroyed here.  We have
+    # to add this hack to really destroy it.
+    Glib::Idle->add (sub { Gtk2->main_quit; return FALSE; });
+    Gtk2->main;
 }
 
 MAIN: while (1) {
@@ -292,29 +298,30 @@ sub show_slide
     # Display an HTML page.
     if ($slide->{ext} eq "html") {
         # MozEmbed is incredibly crashy, so we run ourself as a
-        # subprocess, so when it segfaults we don't care.
+        # subprocess, so when it segfaults we don't care.  If all goes
+        # well and it doesn't crash, it should print a line 'RESULT FOO'
+        # where 'FOO' is the instruction (eg. 'NEXT', 'PREV', 'QUIT' etc).
         my @cmd = ($0, "--mozembed");
         push @cmd, "--mozembed-first" if exists $slide->{first};
         push @cmd, "--mozembed-last" if exists $slide->{last};
-        my $cwd = getcwd;
-        my $url = "file://" . $cwd . "/" . $slide->{name};
+        my $url = "file://$talkdir/" . $slide->{name};
         push @cmd, $url;
-        system (@cmd);
-        die "failed to execute subcommand: ", join(" ", @cmd), ": $!\n"
-            if $? == -1;
-        if ($? & 127) {
-            # Subcommand probably segfaulted, just continue to next slide.
-            return "NEXT";
-        } else {
-            my $r = $? >> 8;
-            if ($r == 0) {
-                return "NEXT";
-            } elsif ($r == 1) {
-                return "PREV";
-            } elsif ($r == 2) {
-                return "QUIT";
+       print STDERR "running subcommand: ", join (" ", @cmd), "\n"
+           if $verbose;
+        open CMD, "-|", @cmd
+            or die "failed to execute subcommand: ", join(" ", @cmd), ": $!\n";
+        my $r;
+        while (<CMD>) {
+            if (/^RESULT ([A-Z]+.*)/) {
+                $r = $1;
+                print STDERR "subcommand result: $r\n" if $verbose;
+                last;
             }
         }
+        # No RESULT line?  Subcommand probably segfaulted, just
+        # continue to next slide.
+        $r ||= "NEXT";
+        return $r;
     }
     # Run a shell command.
     elsif ($slide->{ext} eq "sh") {
@@ -393,8 +400,6 @@ sub show_slide
 # killing the whole program.
 sub run_mozembed
 {
-    my $r = 0;
-
     my $w = Gtk2::Window->new ();
     my $vbox = Gtk2::VBox->new ();
     my $moz = Gtk2::MozEmbed->new ();
@@ -409,17 +414,20 @@ sub run_mozembed
     $w->add ($vbox);
 
     my $bnext = Gtk2::Button->new ("Next slide");
-    $bnext->signal_connect (clicked => sub { $r = 0; $w->destroy });
+    $bnext->signal_connect (clicked =>
+                            sub { print "RESULT NEXT\n"; $w->destroy });
     $bnext->set_sensitive (!$mozembed_last);
     $bbox->add ($bnext);
 
     my $bback = Gtk2::Button->new ("Back");
-    $bback->signal_connect (clicked => sub { $r = 1; $w->destroy });
+    $bback->signal_connect (clicked =>
+                            sub { print "RESULT PREV\n"; $w->destroy });
     $bback->set_sensitive (!$mozembed_first);
     $bbox->add ($bback);
 
     my $bquit = Gtk2::Button->new ("Quit");
-    $bquit->signal_connect (clicked => sub { $r = 2; $w->destroy });
+    $bquit->signal_connect (clicked =>
+                            sub { print "RESULT QUIT\n"; $w->destroy });
     $bbox->add ($bquit);
     $bbox->set_child_secondary ($bquit, 1);
 
@@ -432,7 +440,7 @@ sub run_mozembed
     $moz->load_url ($ARGV[0]);
     Gtk2->main;
 
-    exit $r;
+    exit 0;
 }
 
 1;
@@ -478,6 +486,8 @@ That just ensures that I can put common styling instructions for all
 my slides in a single file (C<style.css>), and I have one place where
 I can add all Javascript, if I need to use any (C<code.js>).
 
+=head3 BACKGROUNDS, FONTS AND LOGOS
+
 To add a common background and font size to all slides, put this in
 C<style.css>:
 
@@ -486,11 +496,43 @@ C<style.css>:
      background: url(background-image.jpg) no-repeat;
  }
 
+To add a logo in one corner:
+
+ body {
+     background: url(logo.jpg) top right no-repeat;
+ }
+
+=head3 SCALING AND CENTERING
+
 Scaling slide text and images so that they appear at the same
 proportionate size for any screen resolution can be done using
 Javascript.  (See
 L<https://developer.mozilla.org/En/DOM/window.innerHeight>).
 
+If you want to center text horizontally, use CSS, eg:
+
+ p.center {
+     text-align: center;
+ }
+
+To center text vertically, CSS3 is supposed to offer a solution some
+time, but while you're waiting for that try
+L<http://www.w3.org/Style/Examples/007/center#vertical>.
+
+=head3 PREVIEWING HTML
+
+I find it helpful to have Firefox open to display the HTML files and
+styles as I edit them.  Just start firefox in the talk directory:
+
+ firefox file://$(pwd) &
+
+When you edit an HTML file, click the Firefox reload button to
+immediately see your changes.
+
+Tech Talk PSE uses Mozilla embedding to display HTML, which uses the
+same Mozilla engine as Firefox, so what you should see in Firefox
+should be identical to what Tech Talk PSE displays.
+
 =head2 CREATING FIGURES
 
 Use your favorite tool to draw the figure, convert it to an image (in
@@ -546,9 +588,16 @@ terminal.
 In C<functions>, I have:
 
  # -*- shell-script -*-
+ # Place any local environment variables required in 'local'.
+ if [ -f local ]; then source local; fi
  export PS1="$ "
- export HISTFILE=/tmp/history
+ export HISTFILE=$talkdir/history
  rm -f $HISTFILE
+ touch $HISTFILE
  
  add_history ()
  {
@@ -557,6 +606,11 @@ In C<functions>, I have:
  
  terminal ()
  {
+     # Make $HISTFILE unwritable so the shell won't update it
+     # when it exits.
+     chmod -w $HISTFILE
+     # Run gnome-terminal.
      exec \
          gnome-terminal \
          --window \
@@ -617,6 +671,13 @@ When running shell scripts, the current directory is also set to be
 the directory containing the talk files, so the same rules about using
 relative paths apply there too.
 
+The environment variable C<$talkdir> is exported to scripts and it
+contains the absolute path of the directory containing the talk files.
+When a script is run, the current directory is the same as
+C<$talkdir>, but if your script changes directory (eg. into a
+subdirectory containing supporting files) then it can be useful to use
+C<$talkdir> to refer back to the original directory.
+
 =head1 WHAT MAKES A GOOD TALK
 
 I like what Edward Tufte writes, for example his evisceration of