6 $semicolon = ";"; # help out stupid emacs
7 $title = "Ardour Shortcuts";
21 $winkey = 'Mod4\>\<Super';
26 GetOptions ("platform=s" => \$platform,
27 "winkey=s" => \$winkey,
28 "cheatsheet" => \$make_cheatsheet,
29 "accelmap" => \$make_accelmap,
30 "merge=s" => \$merge_from);
32 if ($platform eq "osx") {
34 $gtk_modifier_map{'PRIMARY'} = 'Primary';
35 $gtk_modifier_map{'SECONDARY'} = 'Control';
36 $gtk_modifier_map{'TERTIARY'} = 'Shift';
37 $gtk_modifier_map{'LEVEL4'} = 'Mod1';
38 $gtk_modifier_map{'WINDOW'} = 'Control';
40 $cs_modifier_map{'PRIMARY'} = 'Cmd';
41 $cs_modifier_map{'SECONDARY'} = 'Control';
42 $cs_modifier_map{'TERTIARY'} = 'Shift';
43 $cs_modifier_map{'LEVEL4'} = 'Mod1';
44 $cs_modifier_map{'WINDOW'} = 'Control';
46 $mouse_modifier_map{'PRIMARY'} = 'Cmd';
47 $mouse_modifier_map{'SECONDARY'} = 'Ctrl';
48 $mouse_modifier_map{'TERTIARY'} = 'Shift';
49 $mouse_modifier_map{'LEVEL4'} = 'Opt';
50 $mouse_modifier_map{'WINDOW'} = 'Ctrl';
54 $gtk_modifier_map{'PRIMARY'} = 'Control';
55 $gtk_modifier_map{'SECONDARY'} = 'Alt';
56 $gtk_modifier_map{'TERTIARY'} = 'Shift';
57 $gtk_modifier_map{'LEVEL4'} = $winkey;
58 $gtk_modifier_map{'WINDOW'} = 'Alt';
59 $gtk_modifier_map{$winkey} => 'Win';
61 $cs_modifier_map{'PRIMARY'} = 'Control';
62 $cs_modifier_map{'SECONDARY'} = 'Alt';
63 $cs_modifier_map{'TERTIARY'} = 'Shift';
64 $cs_modifier_map{'LEVEL4'} = 'Win';
65 $cs_modifier_map{'WINDOW'} = 'Alt';
66 $cs_modifier_map{$winkey} => 'Win';
68 $mouse_modifier_map{'PRIMARY'} = 'Ctl';
69 $mouse_modifier_map{'SECONDARY'} = 'Alt';
70 $mouse_modifier_map{'TERTIARY'} = 'Shift';
71 $mouse_modifier_map{'LEVEL4'} = 'Win';
72 $mouse_modifier_map{'WINDOW'} = 'Alt';
73 $mouse_modifier_map{$winkey} => 'Win';
77 'asciicircum' => '\\verb=^=',
80 'bracketright' => ']',
82 'braceright' => '\\}',
83 'backslash' => '$\\backslash$',
85 'rightanglebracket' => '>',
86 'leftanglebracket' => '<',
96 'rightarrow' => '$\rightarrow$',
97 'leftarrow' => '$\\leftarrow$',
98 'uparrow' => '$\\uparrow$',
99 'downarrow' => '$\\downarrow$',
100 'Page_Down' => 'Page Down',
101 'Page_Up' => 'Page Up',
109 open (BINDINGS, $merge_from) || die ("merge from bindings: file not readable");
111 next if (/^$semicolon/);
112 if (/^\(gtk_accel/) {
114 chop; # closing parenthesis
116 ($junk, $action, $binding) = split;
117 $merge_bindings{$action} = $binding;
123 if ($make_accelmap && !$merge_from) {
124 print ";; this accelmap was produced by tools/fmt-bindings\n";
128 next if /^$semicolon/;
140 $group_names{$group_key} = $group_name;
141 $group_text{$group_key} = $group_text;
142 $group_numbering{$group_key} = $group_number;
143 # each binding entry is 2 element array. bindings
144 # are all collected into a container array. create
145 # the first dummy entry so that perl knows what we
147 $group_bindings{$group_key} = [ [] ];
152 ($group_key,$group_name) = split (/\s+/, $_, 2);
162 $group_names{$group_key} = $group_name;
163 $group_text{$group_key} = $group_text;
166 next if (/^[ \t]+$/);
176 ($key,$action,$binding,$text) = split (/\|/, $_, 4);
178 # substitute bindings
180 $gtk_binding = $binding;
183 $lookup = "<Actions>/" . $action;
184 if ($merge_bindings{$lookup}) {
185 $binding = $merge_bindings{$lookup};
188 # forced inclusion of bindings from template
190 # this action is not defined in the merge from set, so forget it
196 # print the accelmap output
199 # remove + and don't print it in the accelmap
202 # include this in the accelmap
203 if (!$merge_from && $make_accelmap) {
204 foreach $k (keys %gtk_modifier_map) {
205 $gtk_binding =~ s/\@$k\@/$gtk_modifier_map{$k}/;
207 print "(gtk_accel_path \"<Actions>/$action\" \"$gtk_binding\")\n";
212 # do not include this binding in the cheat sheet
216 $bref = $group_bindings{$key};
217 push (@$bref, [$binding, $text]);
225 if ($make_accelmap || !$make_cheatsheet) {
229 # Now print the cheatsheet
231 $boilerplate_header = <<END_HEADER;
232 \\documentclass[10pt,landscape]{article}
233 \\usepackage{multicol}
236 \\usepackage{palatino}
237 \\usepackage{geometry}
239 \\setlength{\\parskip}{0pt}
240 \\setlength{\\parsep}{0pt}
241 \\setlength{\\headsep}{0pt}
242 \\setlength{\\topskip}{0pt}
243 \\setlength{\\topmargin}{0pt}
244 \\setlength{\\topsep}{0pt}
245 \\setlength{\\partopsep}{0pt}
247 % This sets page margins to .5 inch if using letter paper, and to 1cm
248 % if using A4 paper. (This probably isnott strictly necessary.)
249 % If using another size paper, use default 1cm margins.
250 \\ifthenelse{\\lengthtest { \\paperwidth = 11in}}
251 { \\geometry{top=.5in,left=1in,right=0in,bottom=.5in} }
252 {\\ifthenelse{ \\lengthtest{ \\paperwidth = 297mm}}
253 {\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
254 {\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
257 % Turn off header and footer
260 % Redefine section commands to use less space
262 \\renewcommand{\\section}{\\\@startsection{section}{1}{0mm}%
263 {-1ex plus -.5ex minus -.2ex}%
265 {\\normalfont\\large\\bfseries}}
266 \\renewcommand{\\subsection}{\\\@startsection{subsection}{2}{0mm}%
267 {-1explus -.5ex minus -.2ex}%
269 {\\normalfont\\normalsize\\bfseries}}
270 \\renewcommand{\\subsubsection}{\\\@startsection{subsubsection}{3}{0mm}%
271 {-1ex plus -.5ex minus -.2ex}%
273 {\\normalfont\\small\\bfseries}}
276 % Do not print section numbers% Do not print section numbers
277 \\setcounter{secnumdepth}{0}
279 \\setlength{\\parindent}{0pt}
280 \\setlength{\\parskip}{0pt plus 0.5ex}
282 %-------------------------------------------
288 \\begin{multicols}{3}
291 $boilerplate_footer = <<END_FOOTER;
292 \\rule{0.3\\linewidth}{0.25pt}
295 Copyright \\copyright\\ 2009 ardour.org
297 % Should change this to be date of file, not current date.
298 %\\verb!$Revision: 1.13 $, $Date: 2008/05/29 06:11:56 $.!
300 http://ardour.org/manual
306 if ($make_cheatsheet) {
307 print $boilerplate_header;
308 print "\\begin{center}\\Large\\bf $title \\end{center}\n";
311 @groups_sorted_by_number = sort { $group_numbering{$a} <=> $group_numbering{$b} } keys %group_numbering;
313 foreach $gk (@groups_sorted_by_number) {
314 # $bref is a reference to the array of arrays for this group
315 $bref = $group_bindings{$gk};
317 if (scalar @$bref > 1) {
318 print "\\section{$group_names{$gk}}\n";
320 if (!($group_text{$gk} eq "")) {
321 print "$group_text{$gk}\n\\par\n";
324 # ignore the first entry, which was empty
328 # find the longest descriptive text (this is not 100% accuracy due to typography)
333 for $bbref (@$bref) {
334 # $bbref is a reference to an array
338 # if there is a linebreak, just use everything up the linebreak
339 # to determine the width
342 if ($text =~ /\\linebreak/) {
343 $matchtext = s/\\linebreak.*//;
347 if (length ($matchtext) > $maxtextlen) {
348 $maxtextlen = length ($matchtext);
349 $maxtext = $matchtext;
354 # mouse mode: don't extend max text at all - space it tight
362 print "\\settowidth{\\MyLen}{\\texttt{$maxtext}}\n";
363 print "\\begin{tabular}{\@{}p{\\the\\MyLen}%
364 \@{}p{\\linewidth-\\the\\MyLen}%
367 # sort the array of arrays by the descriptive text for nicer appearance,
370 for $bbref (sort { @$a[1] cmp @$b[1] } @$bref) {
371 # $bbref is a reference to an array
373 $binding = @$bbref[0];
376 if ($binding =~ /:/) { # mouse binding with "where" clause
377 ($binding,$where) = split (/:/, $binding, 2);
381 # mouse mode - use shorter abbrevs
382 foreach $k (keys %mouse_modifier_map) {
383 $binding =~ s/\@$k\@/$mouse_modifier_map{$k}/;
386 foreach $k (keys %cs_modifier_map) {
387 $binding =~ s/\@$k\@/$cs_modifier_map{$k}/;
391 $binding =~ s/></\+/g;
395 # substitute keycode names for something printable
397 $re = qr/${ \(join'|', map quotemeta, keys %keycodes)}/;
398 $binding =~ s/($re)/$keycodes{$1}/g;
400 # split up mouse bindings to "click" and "where" parts
402 if ($gk eq "mobject") {
403 print "{\\tt @$bbref[1] } & {\\tt $binding} {\\it $where}\\\\\n";
405 print "{\\tt @$bbref[1] } & {\\tt $binding} \\\\\n";
409 print "\\end{tabular}\n";
414 print $boilerplate_footer;