2 eval 'exec perl -S $0 ${1+"$@"}'
3 if $running_under_some_shell;
5 #-----------------------------------------------------------------------------
7 # setext.pl -- Structure Enhanced Text Converter (to HTML or simple text)
9 # $Id: setext,v 1.10 2002/11/15 12:21:14 edg Exp $
11 # Copyright (c) 2000 Steven Haehn
13 # This is free software; you can redistribute it and/or modify it under the
14 # terms of the GNU General Public License as published by the Free Software
15 # Foundation; either version 2 of the License, or (at your option) any later
18 # This software is distributed in the hope that it will be useful, but WITHOUT
19 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
23 # You should have received a copy of the GNU General Public License along with
24 # software; if not, write to the Free Software Foundation, Inc., 59 Temple
25 # Place, Suite 330, Boston, MA 02111-1307 USA
27 #-----------------------------------------------------------------------------
29 # The concept of setext documents is the brain child of Ian Feldman.
30 # Some typotag terms used herein were originally implemented in a perl script
31 # by Tony Sanders, which is the inspirational source for this work
32 # (http://www.bsdi.com/setext). This perl script understands the original
33 # typotags, plus extras needed for hypertext links, conditional text, and
36 # Samples of setext documents are regularly provided to those folks which
37 # receive the TidBITS publication from www.tidbits.com in their e-mail.
39 # This program is really two programs crammed into one file. The two separate
40 # pieces share lots of code. Instead of having 3 separate files, one of
41 # them being a perl library with the shared code, there was a desire to keep
42 # everything rolled up in one suitcase.
44 #-----------------------------------------------------------------------------
46 # GENERAL TRANSLATOR ROUTINES NEDIT HELP SOURCE CODE GENERATION ROUTINES
48 # check_target_reference collect_internal_hypertext_references
49 # count emit_copyright
51 # emit_paragraph emit_helpTitles
52 # emit_setext_definition emit_help_header
53 # extract_fields emit_help_label
54 # extract_menu_info emit_help_menu
55 # extract_menu_init emit_help_menu_text
56 # get_menu_item emit_help_topic
57 # get_setext get_menu_text
58 # is_member get_newline
59 # parse_setext get_style
60 # recover_extractions get_style_name
61 # replace_underlines is_known_link
62 # show_usage locate_menu_text
63 # to_state make_NEdit_menu_code
64 # translate_setext print_menu
67 # TYPOTAG TRANSLATION ROUTINES
69 # help_bold_tt text_bold_tt html_bold_tt
70 # help_bullet_tt text_bullet_tt html_bullet_tt
71 # help_emit_line text_emit_line html_emit_line
72 # help_final text_final html_final
73 # help_finishing text_finishing html_finishing
74 # help_hot_tt text_hot_tt html_hot_tt
75 # help_indent text_indent html_indent
76 # help_init text_init html_init, html_init_title
77 # help_italic_tt text_italic_tt html_italic_tt
78 # help_line_break text_line_break html_line_break
79 # help_line_tt text_line_tt html_line_tt
80 # help_quote_tt text_quote_tt html_quote_tt
81 # help_section_tt text_section_tt html_section_tt
82 # help_target_tt text_target_tt html_target_tt
83 # help_title text_title html_title
84 # help_underline_tt text_underline_tt html_underline_tt
86 # help_fixed_styles html_enter_list, html_leave_list
87 # help_proportional_styles html_enter_pre, html_leave_pre
88 # fix_target_tt html_enter_quote, html_leave_quote
92 #-----------------------------------------------------------------------------
94 use Getopt::Long; # for parsing the program command line (GetOptions)
95 use File::Basename; # for trimming off directory names from files (basename)
98 #-------------------------------------------------------------------------------
103 my $date = "Feb 14, 2002";
105 print "$pgm: Version $version, $date.\n";
109 #-------------------------------------------------------------------------------
114 print "Usage: $pgm [ -dhHStTVw ][-c conditional][-v name=value] \\\n";
115 print " [setext_file [converted_file]]\n";
117 print " $pgm {-mp} [-c conditional][-M menuSuffix][-v name=value] setext_file\n";
119 print " The first form of $pgm is used to convert Structure Enhanced TEXT\n";
120 print " documents into HTML or simple text documents.\n";
121 print " The second form is specific to generating NEdit help menu code\n";
122 print " from a setext document with Menu and Help directives.\n";
124 print " -c conditional text definitions, separated by commas.\n";
125 print " -d do not automatically make titles hypertext references (HTML only)\n";
126 print " -h show this usage clause.\n";
127 print " -H convert setext_file to HyperText Markup Language (HTML).\n";
128 print " -m generate NEdit help menu code files.\n";
129 print " -M name NEdit help code files with this suffix.\n";
130 print " -p do option -m and print out NEdit help elements.\n";
131 print " -S convert setext_file into separate HTML files.\n";
132 print " -t convert setext_file to simple text (default).\n";
133 print " -T emit setext typotag definitions in use.\n";
134 print " -v defines variable name and assigns it the given value.\n";
135 print " (more than one occurrence of -v can be made) The variables\n";
136 print " are made available for use within the setext document parsing.\n";
137 print " -V display the version of this setext script.\n";
138 print " -w do not emit warnings about missing variables.\n";
140 print " When the converted_file argument is missing, STDOUT is used.\n";
141 print " When the setext_file argument is missing, STDIN is used.\n";
143 print " To get conditional text within a setext document to be displayed,\n";
144 print " supply a definition tag through the -c option. For example,\n";
146 print " $pgm -c NEDITDOC help.etx nedit.doc\n";
148 print " would generate a plain text document, nedit.doc, from the source\n";
149 print " help.etx, including/excluding text marked with 'NEDITDOC'\n";
150 print " conditional text markers, also known as 'maybe' typotags.\n";
156 #---------------------------------------------------------------------------
157 # This is a GetOptions call back function for gleaning variables from
158 # the command line so that they can be available to the setext parsing
159 # without having to appear in the setext document. The expected form
160 # on the command line is: -v variableName=value. For example, -v version=5.2
161 #---------------------------------------------------------------------------
164 my $optionName = shift;
165 my $optionValue = shift;
166 my ( $varName, $varValue ) = split( "=", $optionValue );
169 print STDERR "Missing value for variable '$varName'\n";
170 $Getopt::Long::error++;
174 #-----------------------------------------------------
175 # By trimming off leading and trailing spaces allows
176 # data entry like this: "version = 5.2 of Oct. 2001".
177 #-----------------------------------------------------
178 $varName =~ s/$trim_spaces/$2/o;
179 $varValue =~ s/$trim_spaces/$2/o;
181 $variables{ $varName } = $varValue;
184 #-------------------------------------------------------------------------------
186 sub emit_setext_definition
188 print <<END_OF_DEFINITION_TEXT;
193 The following table contains typotags recognized by
194 $pgm. The "setext form" column in the table
195 is formatted such that the left most character of
196 the column represents the first character in a line
197 of setext. The circumflex character (^) means that
198 the characters of the typotag are significant only
199 when they are anchored to the front of the setext
200 line. This definition is a sample of a setext document.
201 Consequently, it must be put through the program so
202 that you can view the actual "setext form" of some
203 of the typotags. Thus, issue the following commands
204 to get a proper text view of the table below.
206 $pgm -T > typotags.etx
209 ============ =================== ==================
210 ! name of setext form acted upon or
211 ! the typotag of typotag displayed as
212 !============ =================== ==================
213 ! title-tt "Title a title
214 ! =====" in chosen style
215 !------------ ------------------- ------------------
216 ! subhead-tt "Subhead a subhead
217 ! -------" in chosen style
218 !------------ ------------------- ------------------
219 ! section-tt ^#> section-text a section heading
222 !------------ ------------------- ------------------
223 ! indent-tt ^ lines indented lines undented
224 ! ^ by 2 spaces and unfolded
225 !------------ ------------------- ------------------
226 ! bold-tt **[multi]word** 1+ bold word(s)
227 ! italic-tt ~multi word~ 1+ italic word(s)
228 !underline-tt [_multi]_word_ underlined text
229 ! hot-tt [multi_]word_ 1+ hot word(s)
230 ! quote-tt ^>[space][text] > [mono-spaced]
231 ! bullet-tt ^*[space][text] [bullet] [text]
232 ! untouch-tt `_quoted typotag!_` `_left alone!_`
233 ! notouch-tt ^!followed by text text-left-alone
234 ! field-tt |>name[=value]<| value of name
235 ! line-tt ^ --- horizontal rule
236 !------------ ------------------- ------------------
237 ! href-tt ^.. \@_word URL jump to address
238 ! note-tt ^.. \@_word Note:("*") ("cause error")
239 ! target-tt \@_[multi_]word [multi ]word
240 !------------ ------------------- ------------------
241 ! twobuck-tt \$\$ [last on a line] [parse another]
242 ! suppress-tt ^..[space][not dot] [line hidden]
243 ! twodot-tt ^..[alone on a line] [taken note of]
244 !------------ ------------------- ------------------
245 ! maybe-tt ^.. ? name[~] text show text when
247 ! maybenot-tt ^.. ! name[~] text show text when
249 ! endmaybe-tt ^.. ~ name end of a multi-
251 !------------ ------------------- ------------------
252 ! passthru-tt ^!![text] text emitted
254 !------------ ------------------- ------------------
255 ! escape-tt @\@x where 'x' is x is what remains
256 ! escaped character @@@@ needed for 1 @@
257 ============ =================== ==================
259 Only one instance of the element subhead-tt (or, in its
260 absence, title-tt) is absolutely _required_ for a text to
261 be considered a valid setext.
263 All the elements, but subhead-tt, are in effect optional,
264 that is, not necessary for a setext to be declared as
265 such. The target-tt element allows the hypertext link
266 definition of href-tt to be within the same setext. The
267 actual reference (href-tt) of the target would look like:
269 .. _word #reference_within_document
271 !Multiple line maybe[not]-tt (conditional text regions)
272 !are introduced as ".. ? name~" or ".. ! name~" and are
273 !terminated with ".. ~ name", on a separate line. Single
274 !line maybe[not]-tt do not use the '~' character and are
275 !terminated with the end of the line. The special
276 !conditional text region named "html" allows a mixture of
277 !setext and HTML tags. Nesting of these typotags is
278 !allowed. For instance, if there are three conditional
279 !regions, A, B, and C, C can be nested inside B, which can
280 !be nested inside A (eg. A-B-C...C-B-A). Note that a
281 !surrounding region cannot end before one of its inner
282 !regions is terminated (eg. of illegal nesting
283 !A-B-C...C-A-B, where A terminated prior to B.
285 Field typotags are used to define and reference values.
286 Field definitions can only occur within a suppress-tt.
287 For example: ".. `|>author=Steven Haehn<|`"
288 Field references (eg. |>author<|) can occur in any
289 printable text. If there is no known value for the
290 field, it will remain unchanged and appear as written
292 END_OF_DEFINITION_TEXT
294 #---------------------------------------------------------------
295 # Emit any predefined variables so user knows what is available.
296 #---------------------------------------------------------------
300 print " The following are predefined for use in a field-tt\n";
301 print " for any setext document translated by this utility.\n";
304 foreach $key ( sort keys %variables )
306 print " $key = $variables{$key}\n";
314 #-------------------------------------------------------------------------------
316 $pgm = basename( $PROGRAM_NAME );
318 #==========================
319 # Global shared definitions
320 #==========================
321 $um = "\375"; # untouchable marker
322 $vm = "\374"; # variable marker
323 $escMrk = "\33"; # internal escape marker
324 $trim_spaces = '(\s*)(.*?)(\s*)$';
325 %variables = ( date => &date(), Date => &date("D"), year => &date("y") );
326 @cond_text_definitions = ();
327 $make_title_href = 1;
329 #---------------------------------------------------------
330 # Look for following options, complain about unknown ones.
331 #---------------------------------------------------------
332 Getopt::Long::config( "noignorecase" );
336 'c=s', # conditional text definitions, separated by commas
337 'd', # do not make titles hypertext references (HTML only)
339 'H', # create HTML from setext input
340 'm', # create NEdit help menu code from setext input
341 'M=s', # name NEdit help code files with this suffix
342 'p', # same as 'm' but with debug printout
343 'S', # generate separate HTML files for each subsection
344 't', # create text from setext input
345 'T', # emit setext typo-tag document
346 'v=s', \&declare_variable,
347 'V', # emit setext script version information
348 'w' # do not emit warning messages.
352 #-----------------------------------
353 # Glean only those options specified
354 #-----------------------------------
355 $opt_c && (@cond_text_definitions = split( ",", $opt_c ));
356 $opt_d && ($make_title_href=0);
357 $opt_h && show_usage();
358 $opt_H && ($convert_to = "html");
359 $opt_m && do { $make_menu = 1; $convert_to = "help" };
360 $opt_M && ($helpSuffix = $opt_M );
361 $opt_p && do { $make_menu = 1; $convert_to = "help"; $print_menu = 1 };
362 $opt_S && do { $separate_html_files=1; $make_title_href=1 };
363 $opt_t && ($convert_to = "text");
364 $opt_T && emit_setext_definition();
365 $opt_V && (emit_version());
366 $opt_w && ($noWarn = 1);
368 #--------------------------------------------------------------
369 # Setext Parser states.
371 # The names are used to construct "enter_" & "leave_" elements
372 # in the state_change hash table required to be initialized
373 # by language specific initialization routines (see html_init).
374 #--------------------------------------------------------------
380 #----------------------------
381 # Typotag Pattern Definitions
382 #----------------------------
383 $bold_tt = '\*\*([^\*]+)\*\*([^\*]|$)';
384 $bullet_tt = '^\* ([^ ])';
385 $empty_line = '^\s*$';
388 $field_tt = "(${fld_left}[^<]+$fld_right)";
389 $field_content = "${fld_left}([^<]+)$fld_right";
390 $hot_tt = '\b([\S]*)_\b';
391 $href_tt = '^\.\.\s+_([\S]*)\s+(.*)\s*';
392 $indent_tt = '^ ([^ ])';
394 $internal_href = "^$intHrefMrk(.*)\$";
395 $italic_tt = '~([^~]*)~';
396 $line_tt = '^ ---*$';
398 $passthru_tt = '^!!';
400 $section_tt = '^([1-6])>';
401 $subtitle_tt = '^---';
402 $suppress_tt = '^\.\.';
403 $target_tt = '(?!(^|\s)_[\S]+_(\s|\W|$))(^|\s)_([\S]+)'; # not underline, then target
405 $twobuck_tt = '^\s*\$\$\s*$';
406 $underline_tt = '\b_([\S]*)_\b';
407 $untouch_tt = "\\s*(`[^`]+[`'])(?=\\s|\\W|\$)";
408 $variable_def = '\s*(\w+)\s*([^=]*(=(.+)))?'; # $1 = name, $4 = value
410 $escape_tt = "@"; # the character escape symbol (need @@ to escape @)
411 $needEscaping = "$escape_tt(.)";
412 $escapedFound = "$escMrk(\\d+)$escMrk";
416 $setext_file = $ARGV[0];
417 open SETEXT, "<$setext_file" or die "Can't access $setext_file, $OS_ERROR";
418 make_NEdit_menu_code();
420 else # Global elements for parsing setext
422 #-------------------------
423 # Program option defaults.
424 #-------------------------
425 $setext_file = "-"; # STDIN, allows program to be used as a filter
426 $converted_file = "-"; # STDOUT
427 $convert_to = "text" if $convert_to eq "";
429 #--------------------------------------
430 # Begin processing file specifications.
431 #--------------------------------------
432 $setext_file = $ARGV[0] if $ARGV[0] ne "";
433 open SETEXT, "<$setext_file" or die "Can't access $setext_file, $OS_ERROR";
437 $converted_file = $ARGV[1];
438 $convert_to = "html" if $converted_file =~ /\.html$/; # in case -H forgotten
441 open CONVERT, ">$converted_file" or die "Can't create $converted_file, $OS_ERROR";
445 #-------------------------------------------------------------------------------
446 #-------------------------------------------------------------------------------
447 #-------------------------------------------------------------------------------
451 #--------------------------------------
452 # Adding conversion type to conditional
453 # text definitions for convenience.
454 #--------------------------------------
455 push @cond_text_definitions, $convert_to;
457 get_setext( SETEXT, \@cond_text_definitions, \@data );
459 extract_menu_info( \@data )
460 if( $convert_to eq "html" && $separate_html_files );
462 chomp @data; # remove the newline character from each line.
464 register_tt_translationFunctions( $convert_to );
466 parse_setext( \@data );
469 #-------------------------------------------------------------------------------
471 sub make_NEdit_menu_code
473 #--------------------------------
474 # Supply a default NEdit version.
475 #--------------------------------
476 $neditDefaultMarker = "NEdit release of ";
477 $variables{ version } = $neditDefaultMarker . date()
478 if (not exists $variables{ version } or
479 $variables{ version } eq "default");
481 #--------------------------------------
482 # Adding conversion type to conditional
483 # text definitions for convenience.
484 #--------------------------------------
485 push @cond_text_definitions, $convert_to;
487 get_setext( SETEXT, \@cond_text_definitions, \@data );
488 extract_menu_info( \@data );
489 register_tt_translationFunctions( $convert_to );
492 #-------------------------------------------------------------------------------
496 my $setextData = shift;
498 local($crnt_state, $fold, $a, $i, $unt, $lineNo);
505 foreach (@$setextData)
507 $lineNo++; # current location in data array
509 #--------------------------
510 # process title information
511 #--------------------------
512 (/$title_tt/i or /$subtitle_tt/i) && do {
518 /$section_tt/o && do {
524 /$passthru_tt/ && do {
529 next if ( /$suppress_tt/ or /$twobuck_tt/ );
531 #--------------------------------------------------
532 # handle line breaks, only one empty line gets out.
533 #--------------------------------------------------
534 if ( /$empty_line/) {
536 $fold = &$do_line_break( $fold );
540 $fold = 0; # no more empty lines
542 /$line_tt/ && do { &$do_line_tt(); next; };
547 if ( /$quote_tt/o ) { &to_state( $QUOTE ) }
548 elsif ( /$bullet_tt/o ) { &to_state( $LIST ) }
549 elsif ( /$indent_tt/o ) { &to_state( $FMT ) }
550 else { &to_state( $PRE_FMT ) }
552 if( /$notouch_tt/o ) { s/$notouch_tt/ /o; }
555 #--------------------------------------------
556 # Handle the untouchables first.
557 # Mark their locations for later replacement.
558 # (see recover_extractions)
559 #--------------------------------------------
560 for( $i = scalar( @untouchable ); /$untouch_tt/o; $i++ )
563 $unlen = length( $unt );
564 $unloc = index( $_, $unt );
565 $untouchable[ $i ] = $unt;
566 $front = substr( $_, 0, $unloc );
567 $back = substr( $_, $unloc+$unlen );
568 $_ = $front . $um . $back;
586 #-------------------------------------------------------------------------------
588 sub register_tt_translationFunctions
590 my $conversion_type = shift;
592 #----------------------------------------------------
593 # Register call-back functions for typotag processing
594 #----------------------------------------------------
595 $do_bold_tt = "${conversion_type}_bold_tt";
596 $do_bullet_tt = "${conversion_type}_bullet_tt";
597 $do_emit_line = "${conversion_type}_emit_line";
598 $do_final = "${conversion_type}_final";
599 $do_hot_tt = "${conversion_type}_hot_tt";
600 $do_indent_tt = "${conversion_type}_indent";
601 $do_initialize = "${conversion_type}_init";
602 $do_italic_tt = "${conversion_type}_italic_tt";
603 $do_line_break = "${conversion_type}_line_break";
604 $do_line_tt = "${conversion_type}_line_tt";
605 $do_quote_tt = "${conversion_type}_quote_tt";
606 $do_section_tt = "${conversion_type}_section_tt";
607 $do_target_tt = "${conversion_type}_target_tt";
608 $do_title = "${conversion_type}_title";
609 $do_underline_tt = "${conversion_type}_underline_tt";
611 &$do_initialize; # do any necessary initialization
614 #-------------------------------------------------------------------------------
620 ( $sec,$min,$hour,$mday,$mon,$year,@ignore ) = localtime( time );
621 $month = (January,February,March,April,May,June,July,
622 August,September,October,November,December)[$mon];
623 $year = $year + 1900;
625 return $year if $format eq "y";
626 return "$month $mday, $year" if $format eq "D";
627 return substr($month,0,3) . " $mday, $year";
630 #-------------------------------------------------------------------------------
634 my $given_state = shift;
636 if ( $crnt_state ne $given_state )
638 if( exists $state_change{ "leave_$crnt_state" } )
640 $doStateChange = $state_change{ "leave_$crnt_state" };
644 if( exists $state_change{ "enter_$given_state" } )
646 $doStateChange = $state_change{ "enter_$given_state" };
650 $crnt_state = $given_state;
654 #-------------------------------------------------------------------------------
658 my $whatToCount = shift;
662 $howMany++ while( $line =~ /$whatToCount/g );
666 #-------------------------------------------------------------------------------
671 local $cond_text_region = shift;
673 my ( $field, $variable, $flen, $floc, $front, $back, $v_name, $v_value );
674 my @variable_list = ();
676 #------------------------------------------
677 # Mark all the escaped character sequences.
678 #------------------------------------------
679 while( /$needEscaping/o )
681 $subChar = ord( $1 );
682 s/$needEscaping/$escMrk$subChar$escMrk/o;
685 #-----------------------------------------------------
686 # Collect any field typotags found for later expansion.
687 #-----------------------------------------------------
688 while( /$field_tt/o )
691 $field =~ /$field_content/ && ( $variable = $1 );
693 if( $variable =~ /$variable_def/ ) {
697 #----------------------------------------------
698 # When fields 2 and 3 contain identical strings
699 # then a valid field has been encountered.
700 #----------------------------------------------
706 #-----------------------------------
707 # This is NOT a variable definition.
708 # Have to recover original string.
709 #-----------------------------------
710 $v_name = "_A_${v_name}_Z_"; #internal name
711 $v_value = $variable;
714 #----------------------------------------
715 # Is this only a reference to a variable?
716 #----------------------------------------
717 if ($v_value eq "") {
718 #------------------------------------------------
719 # Only put definitions in the list when it is not
720 # part of a comment. (comments are not emitted)
721 #------------------------------------------------
722 push @variable_list, $v_name unless /$suppress_tt/o;
725 #------------------------------------------------
726 # setting the variable ( |>varName = value<| )
727 # (here $v_value is the value assignment portion)
728 #------------------------------------------------
729 if( /$suppress_tt/o ) {
730 $variables{ $v_name } = $v_value;
732 push @variable_list, $variable;
737 #--------------------------------------
738 # Remove field and replace with marker.
739 #--------------------------------------
740 $flen = length( $field );
741 $floc = index( $_, $field );
742 $front = substr( $_, 0, $floc );
743 $back = substr( $_, $floc+$flen );
744 $_ = $front . $vm . $back;
747 #----------------------------
748 # Fill in any variables found
749 #----------------------------
750 foreach $element ( @variable_list )
752 if( exists $variables{ $element } ) {
753 $value = $variables{ $element }
755 $value = "|>$element<|";
756 print STDERR "$pgm: Undefined variable '$element' used in $setext_file.\n" unless $noWarn;
761 #--------------------------------------------------------
762 # When in a conditional text region that only applies to
763 # HTML translation, change the angle brackets to internal
764 # definitions that will be fixed later. This should allow
765 # for a mixture of setext and HTML language together.
766 #--------------------------------------------------------
767 if ( $cond_text_region eq "html" )
776 #===================================================================
777 # Import setext data from given data stream and pay attention to
778 # conditional text considerations, as described below.
780 # ^.. ? name Conditional text when 'name' is defined.
781 # ^.. ! name Conditional text when 'name' is NOT defined.
784 # Multiple line conditional text when 'name' is defined.
785 # (without suppress-tt, will always appear in translated
786 # document going through non-conditional setext conversion)
790 # Multiple line conditional text when 'name' is NOT defined.
791 # (without suppress-tt, will always appear in translated
792 # document going through non-conditional setext conversion)
795 # This procedure also extracts and applies variable definitions
796 # to the text to be emitted.
797 #===================================================================
802 my $cond_text_definitions = shift;
805 my $conditional_text_marker = '^\.\. ([\?!~])\s*(\S+)\s?(.*)$';
809 my ($tense,$def_nm,$text,$multi_line,$crnt_def);
810 my @cond_text_stack = ();
812 while( $_ = <$stream> )
816 if( /$conditional_text_marker/o )
818 $tense = $1; # positive, negative, or end-of conditional text
822 $multi_line = $def_nm =~ s/~//o;
824 #---------------------------------------------
825 # Reach end of multiple line conditional text?
826 #---------------------------------------------
829 $crnt_def = substr( pop @cond_text_stack, 1 );
831 if( $crnt_def ne $def_nm )
833 print STDERR "Incorrectly nested conditinal text sections near line $lineNbr.\n";
834 print STDERR "Expected end of '$crnt_def', but saw end of '$def_nm'\n";
840 #-----------------------------------------
841 # Entering multiple line conditional text?
842 #-----------------------------------------
844 push @cond_text_stack, "$tense$def_nm";
847 #------------------------------------------
848 # This will also catch any non-space
849 # text found on multiple line conditionals.
850 #------------------------------------------
853 $$data[$i++] = extract_fields( "$text\n", $def_nm )
854 if ($tense eq "?") and is_member( $def_nm, $cond_text_definitions );
855 $$data[$i++] = extract_fields( "$text\n", $def_nm )
856 if ($tense eq "!") and not is_member( $def_nm, $cond_text_definitions );
860 elsif( scalar( @cond_text_stack ) == 0 )
862 $$data[$i++] = extract_fields( $_, "" );
866 #--------------------------------------------------------------------
867 # The top element of the conditional text stack is the current
868 # conditional text area. See if it exists in the definitions list.
869 # When present, we want this line of text, depending on 'tense'.
870 #--------------------------------------------------------------------
871 $element = $cond_text_stack[-1];
872 $tense = substr( $element, 0, 1 );
873 $def_nm = substr( $element, 1 );
877 if( is_member( $def_nm, $cond_text_definitions ) ) {
879 $$data[$i++] = extract_fields( $_, $def_nm );
882 elsif( ! is_member( $def_nm, $cond_text_definitions ) )
885 $$data[$i++] = extract_fields( $_, $def_nm );
891 #-------------------------------------------------------------------------------
893 sub extract_menu_init
897 @menuStack = \@helpMenu;
898 $crntMenu = \@helpMenu;
899 @indentStack = ( 0 );
901 $comment_ind = "^\\.\\."; # setext comment indicator ("..")
902 $menu_element = "${comment_ind} Menu: ";
903 $help_element = "${comment_ind} Help: ";
904 $drop_marker = "_(.)_";
906 $help_code = 9; # special hide-it code indicating not part of help menu
907 $name_length = 0; # determines padding alignment in HelpMenu data emission
909 $subMenuIndicator = "\377";
912 #-------------------------------------------------------------------------------
914 sub extract_menu_info
916 my $thisData = shift;
921 #----------------------------------------------------------------------
922 # For each and every menu item found in the original data (*.etx) file.
923 #----------------------------------------------------------------------
924 while( $_ = get_menu_item( $thisData, \$dataIndex ) )
926 #----------------------------------------------------------------------
927 # Here we want to extract the menu title, help name, optional hideIt
928 # numerical indicator, and optional menu association name.
930 # Expecting: MenuTitle # HelpName [[,]HideItIndicator] [# Association]
931 #----------------------------------------------------------------------
932 if( /^([^#]+)#\s*(\w*)(\s*,\s*)?(\d+)?(\s*#\s*)?(\w+)?/o )
936 $hideItInd = ($4 eq "") ? "0" : $4;
937 $assocName = ($6 eq "") ? $helpName : $6;
938 $helpName =~ s/$trim_spaces/$2/;
939 $assocName =~ s/$trim_spaces/$2/;
941 #------------------------------------------------
942 # Determine to which menu this menu item belongs
943 # using leading whitespace indentation.
944 # Extract menu character mneumonic.
945 #------------------------------------------------
946 $menuTitle =~ /^(\s*)/ && ($nextMenu = length($1)-$crntIndent);
947 $menuTitle =~ s/$trim_spaces/$2/o;
949 $mneumonic = (/$drop_marker/) ? $1 : substr( $menuTitle, 0, 1 );
951 #--------------------------------------------------
952 # Identation greater than previous menu element
953 # indicates that this element is part of a submenu.
954 #--------------------------------------------------
957 @$crntMenu[ $end ] .= $subMenuIndicator; # mark previous element
958 ($menu = $previousTitle) =~ s/ /_/g;
960 push @menuStack, \@$menu;
961 push @indentStack, $nextMenu;
964 #--------------------------------------
965 # Indentation less than previous menu
966 # element indicates leaving a submenu.
967 #--------------------------------------
968 elsif( $nextMenu < 0 )
970 $indentLevel = $indentStack[$menuLevel] + $nextMenu;
976 } while( $indentLevel < $indentStack[$menuLevel] );
979 $crntIndent += $nextMenu;
980 $crntMenu = $menuStack[ $#menuStack ];
981 $end = scalar( @$crntMenu );
982 @$crntMenu[ $end ] = "$mneumonic,$menuTitle,$helpName,$hideItInd";
983 $thisTitle = $menuTitle;
984 $thisTitle =~ s/$drop_marker/$1/;
985 $thisTitle =~ s/ /_/go;
986 $MenuNames{ $thisTitle } = "$menuLevel$assocName";
987 $previousTitle = $menuTitle;
989 #---------------------------------
990 # update data for padding purposes
991 #---------------------------------
992 if( $mneumonic ne $separator and $name_length < length( $helpName ) )
994 $name_length = length( $helpName );
1000 #-------------------------------------------------------------------------------
1007 #-------------------------------------------
1008 # Search each and every data line for either
1009 # a '# Menu: ' line or a '# Help: ' line and
1010 # return remainder of the line.
1011 #-------------------------------------------
1012 while( $$line < scalar( @$setext ) )
1014 $_ = $$setext[ $$line++ ];
1015 return $_ if s/$menu_element//o;
1016 return "$_, $help_code" if s/$help_element//o;
1022 #-------------------------------------------------------------------------------
1024 sub check_target_reference
1033 #-----------------------------------
1034 # Are all titles automatically being
1035 # made into hypertext references?
1036 #-----------------------------------
1037 elsif( $make_title_href ) {
1038 /$title_tt/ && ( $target = $2 );
1039 $target =~ s/$trim_spaces/$2/o;
1040 $target =~ s/ /_/go;
1044 print CONVERT "<A NAME=\"$target\"</A>\n";
1046 # only one target-tt reference of this kind allowed per file.
1047 ($index = is_member( $target, \@nm_ref ))
1048 && do{ splice( @nm_ref, $index-1, 1 ); };
1052 #-------------------------------------------------------------------------------
1060 foreach $member ( @$this_list )
1062 if( $item eq $member )
1072 #-------------------------------------------------------------------------------
1074 sub replace_underlines
1076 my $pattern = shift;
1077 s#$pattern#($text = $1) =~ s,_, ,go; $text; #eg;
1080 #-------------------------------------------------------------------------------
1084 #-----------------------------------------
1085 # Put back any escaped characters in text.
1086 #-----------------------------------------
1087 while( /$escapedFound/ )
1089 $subChar = chr( $1 );
1090 s/$escapedFound/$escape_tt$subChar/;
1094 #-------------------------------------------------------------------------------
1096 sub recover_extractions
1100 #------------------------------------
1101 # Replace escaped characters in text.
1102 #------------------------------------
1103 while( /$escapedFound/ )
1105 $subChar = chr( $1 );
1106 s/$escapedFound/$subChar/;
1109 foreach $element ( @untouchable ) { s/$um/$element/; }
1113 #-------------------------------------------------------------------------------
1117 my $paragraph = shift;
1118 my $line = $left_margin;
1120 @words = split ' ', $paragraph;
1122 #-------------------------------------------------------------
1123 # Flow words onto a line up until the right margin is reached.
1124 #-------------------------------------------------------------
1125 foreach $word ( @words )
1127 if( length( $line ) + length( $word ) + 1 <= $right_margin )
1129 $line = "$line$word ";
1133 print CONVERT "$line\n";
1134 $line = "$left_margin$word ";
1138 #--------------------
1139 # emit any remainder.
1140 #--------------------
1141 print CONVERT "$line\n" if( length( $line ) > length( $left_margin ) );
1144 #-------------------------------------------------------------------------------
1145 # setext to text conversion call-back routines.
1146 # ( in alphabetical order )
1147 #-------------------------------------------------------------------------------
1149 sub text_bold_tt { s/$bold_tt/$1$2/g }
1151 #-------------------------------------------------------------------------------
1155 # don't do anything if this is no bulleted line.
1158 # remove lead-in from paragraph and put the rest in an array
1160 $paragraph =~ s/$bullet_tt/$1/;
1161 @words = split ' ', $paragraph;
1164 # start with text mode bullet character
1166 foreach $word (@words)
1168 if (length($line) + length($word) + 1 <= $right_margin)
1170 # put every word in a line if there's still room
1171 $line = "$line$word ";
1174 # append line to paragraph if full and start a new line
1175 $paragraph = "$paragraph$line\n";
1180 $paragraph = "$paragraph$line";
1182 # remove trailing white space
1183 $paragraph =~ s/\s$//;
1188 #-------------------------------------------------------------------------------
1192 if( /$passthru_tt/ )
1194 s/$passthru_tt//o; # remove typotag and pass line out as is.
1196 print CONVERT "$_\n";
1200 if( $crnt_state ne $FMT && $text_unfolded_line ne "" )
1202 emit_paragraph( &text_finishing($text_unfolded_line) );
1203 $text_unfolded_line = "";
1206 print CONVERT &text_finishing( $_ ), "\n" unless $_ eq $indentingMode;
1210 #-------------------------------------------------------------------------------
1212 sub text_final { emit_paragraph( &text_finishing($text_unfolded_line) ) }
1214 #-------------------------------------------------------------------------------
1219 recover_extractions();
1223 #-------------------------------------------------------------------------------
1228 #---------------------------------------------------------
1229 # The heuristic to prevent Internet addresses from having
1230 # underlines removed, is to check for an '@' character.
1231 #---------------------------------------------------------
1232 if (($text = $1) !~ /\@/ ) {
1239 #-------------------------------------------------------------------------------
1243 s/$indent_tt/$1/o && do {
1244 $text_unfolded_line = "$text_unfolded_line$_ ";
1245 $_ = $indentingMode;
1249 #-------------------------------------------------------------------------------
1254 $text_unfolded_line = ""; # to be used by text_indent & text_emit_line
1255 $left_margin = " "; # for emit_paragraph
1256 $right_margin = 79; # for emit_paragraph
1257 $indentingMode = "?#."; # hopefully unique string not normally found
1259 #----------------------------------------------------------------
1260 # Take all the titles, capitalize and remove title indicator.
1261 #----------------------------------------------------------------
1262 for ($i = 0; $i <= $#data; $i++)
1264 $_ = $data[$i]; # $_ is default for searches
1266 (/$title_tt/ or /$subtitle_tt/) && do {
1267 $titleType = ( /$title_tt/ ) ? "=" : "-";
1268 $data[$i--] = ".."; # suppress title indicator ( --- or === )
1269 $data[$i] =~ s/^\s*//o; # get rid of any leading space.
1270 $this_title = $data[$i];
1272 # Have to fix title if it also happens to be a target-tt.
1273 $this_title =~ /$target_tt/ && do { ($tmp = $4) =~ s,_, ,go; $this_title = $tmp };
1274 $data[$i] = "..$titleType \U$this_title";
1278 #----------------------------------------------------
1279 # NOTE: changing original subtitle-tt search pattern
1280 # to match what was done above.
1281 #----------------------------------------------------
1282 $subtitle_tt = "^\\.\\.- (.*)";
1283 $title_tt = "^\\.\\.= (.*)";
1286 #-------------------------------------------------------------------------------
1288 sub text_italic_tt { s/$italic_tt/$1/g }
1290 #-------------------------------------------------------------------------------
1295 emit_paragraph( &text_finishing($text_unfolded_line) );
1296 $text_unfolded_line = "";
1297 print CONVERT "\n" unless $fold++;
1301 #-------------------------------------------------------------------------------
1303 sub text_line_tt { }
1304 sub text_quote_tt { }
1306 #-------------------------------------------------------------------------------
1310 my $hdr_level = shift;
1313 print CONVERT "\n \U$_\n" if $hdr_level <= 3; # converted to uppercase
1314 print CONVERT "\n $_\n" if $hdr_level > 3; # left alone
1318 #-------------------------------------------------------------------------------
1322 s#$target_tt#($text = $4) =~ s,_, ,go; " $text"; #eg;
1325 #-------------------------------------------------------------------------------
1331 my $lc = substr( $_, 2, 1 );
1333 #-----------------------------------------------------------------
1334 # Incoming text looks like ..= <title text> or ..- <subtitle text>
1335 #-----------------------------------------------------------------
1337 $_ = substr( $_, 4 );
1339 $size = length( $_ );
1341 #-------------------------------------------------
1342 # Going to wrap titles with lines as long as title
1343 #-------------------------------------------------
1344 for( $size = length( $_ ); $size > 0; $size-- )
1348 print CONVERT "$line\n$_\n$line\n";
1351 sub text_underline_tt { replace_underlines( $underline_tt ) }
1353 #-------------------------------------------------------------------------------
1354 # setext to HTML conversion call-back routines.
1355 # ( in alphabetical order )
1356 #-------------------------------------------------------------------------------
1360 #---------------------------------------
1361 # Turn all "**text**" into "<B>text</B>"
1362 #---------------------------------------
1363 s#$bold_tt#${lt}B${gt}$1${lt}/B${gt}$2#g;
1366 #-------------------------------------------------------------------------------
1370 s/$bullet_tt(.*)/ ${lt}li${gt}$1$2${lt}\/li${gt}/;
1373 #-------------------------------------------------------------------------------
1377 if( /$passthru_tt/ )
1379 s/$passthru_tt//o; # remove typotag and pass line out as is.
1381 print CONVERT "$_\n"
1385 print CONVERT &html_finishing( $_ ), "\n";
1389 #-------------------------------------------------------------------------------
1391 sub html_enter_list { print CONVERT "<UL>\n" } # state change activities
1392 sub html_leave_list { print CONVERT "</UL>\n" }
1394 sub html_enter_pre { print CONVERT "<PRE>\n" }
1395 sub html_leave_pre { print CONVERT "</PRE>\n" }
1397 sub html_enter_quote { print CONVERT "<BLOCKQUOTE><PRE>\n" }
1398 sub html_leave_quote { print CONVERT "</PRE></BLOCKQUOTE>\n" }
1400 #-------------------------------------------------------------------------------
1405 print CONVERT "</BODY>\n</HTML>\n";
1407 #----------------------------------------------------
1408 # Report on all internal name references not used up.
1409 #----------------------------------------------------
1410 if( scalar( @nm_ref ) > 0 )
1412 print STDERR "\nMissing reference (target-tt) to the following:\n\n";
1413 for( $i=0; $i < scalar( @nm_ref ); $i++ )
1415 print STDERR " $nm_ref[ $i ]\n";
1420 #-------------------------------------------------------------------------------
1422 sub html_finishing {
1425 s/\&/\&\#38\;/go; s/\</\&\#60\;/go; s/\>/\&\#62\;/go;
1426 s/$lt/</go; s/$gt/>/go; s/$amp/\&/go; # convert markers to real symbols
1428 #-----------------------------------------------
1429 # This fixes the case where an untouchable
1430 # string includes these special html characters.
1431 #-----------------------------------------------
1432 foreach $element ( @untouchable )
1434 $element =~ s/\&/\&\#38\;/go;
1435 $element =~ s/\</\&\#60\;/go;
1436 $element =~ s/\>/\&\#62\;/go;
1438 recover_extractions();
1442 #-------------------------------------------------------------------------------
1446 #--------------------------------------------------
1447 # After finding a hot-tt, substitute all underlines
1448 # with spaces and check to see if the hot-tt had
1449 # a corresponding hypertext reference. Flag it in
1450 # bright, bold red when no hypertext record found.
1451 #--------------------------------------------------
1453 $h = $href{$1}; ($text = $1) =~ s,_, ,go;
1454 $h ? qq'${lt}A HREF="$h"${gt}$text${lt}/A${gt}'
1455 : "${lt}B${gt}${lt}font color=red${gt}--> $text <-- NO HREF!!${lt}/font${gt}${lt}/B${gt}"; #eg;
1458 #-------------------------------------------------------------------------------
1460 sub html_indent { s/$indent_tt/$1/ } # get rid of indent-tt characters
1462 #-------------------------------------------------------------------------------
1469 #---------------------------------------
1470 # Variables needed for HTML conversions.
1471 #---------------------------------------
1472 $lt = "\376"; # "<" marker
1473 $gt = "\377"; # ">" marker
1474 $amp = "\373"; # "&" marker
1478 enter_list => "html_enter_list",
1479 leave_list => "html_leave_list",
1481 enter_pre => "html_enter_pre",
1482 leave_pre => "html_leave_pre",
1484 enter_quote => "html_enter_quote",
1485 leave_quote => "html_leave_quote",
1488 $veryFirstTime = 1; # used to force table of content header out
1490 print CONVERT "<HTML>\n<HEAD>\n";
1492 #------------------------------------------
1493 # Make a first pass over the data, looking
1494 # for hypertext linking information.
1495 #------------------------------------------
1496 for ($i = 0; $i <= $#data; $i++)
1498 $_ = $data[$i]; # $_ is default for searches
1500 #---------------------------------------------------------
1501 # This will pick out targets found in the setext not
1502 # hidden by a suppress-tt, that is, the href-tt below.
1503 # With this check, it is unnecessary to have to include
1504 # the href-tt which uses identical text for internal
1505 # document references. External references need href-tt.
1506 # Have to make sure the match does not pick up elements
1507 # inside a notouch-tt ( eg. `_do_not_want_this_as_target`)
1508 #---------------------------------------------------------
1509 if( /$target_tt/ && substr($`,length($`)-1,1) ne "`" &&
1510 (not /$suppress_tt/) )
1512 $href{ $4 } = "$intHrefMrk$4";
1516 #-------------------------------------------------
1517 # Locate HREF's and save. When no target is given,
1518 # assume the target is internal, with same name.
1519 #-------------------------------------------------
1523 $target = ($2) ? $2 : "$intHrefMrk$hrefID"; # assume internal href.
1524 $href{$hrefID} = $2;
1526 #------------------------------
1527 # Remember internal HREF's not
1528 # already seen for target-tt.
1529 #------------------------------
1530 if( $target =~ /$internal_href/ ) {
1531 if( not is_member( substr( $target, 1), \@nm_ref ) ) {
1538 #---------------------------------------------------------
1539 # The first title-tt or subhead-tt gets <TITLE>...</TITLE>
1540 #---------------------------------------------------------
1541 /$title_tt/ && do { html_init_title("H1", $i); next; };
1542 /$subtitle_tt/ && do { html_init_title("H2", $i); next; };
1545 print CONVERT "</HEAD>\n";
1546 print CONVERT "<BODY>\n";
1548 #----------------------------------------------------
1549 # NOTE: changing original title-tt search pattern
1550 # to match what was done in html_init_title.
1551 #----------------------------------------------------
1552 $title_tt = "^\\.\\.\\s+(<H.>)(.*)(<\\/H.>)";
1555 #-------------------------------------------------------------------------------
1559 local($head, $i) = @_;
1562 $data[$i--] = ".."; # suppress title indicator ( --- or === )
1563 $data[$i] =~ s/^\s*//; # get rid of any leading space in actual title
1564 $this_title = $data[$i];
1566 # Have to fix title if it also happens to be a target-tt.
1567 $this_title =~ /$target_tt/ && do { ($tmp = $4) =~ s,_, ,go; $this_title = $tmp };
1569 #---------------------------------------------------
1570 # Are all titles automatically considered target-tt?
1571 #---------------------------------------------------
1572 if( $make_title_href )
1574 $hyper_ref = $this_title;
1575 $hyper_ref =~ s/ /_/go;
1576 $externalReference =
1577 ($separate_html_files) ? substr("$MenuNames{ $hyper_ref }.html", 1) : "";
1579 $href{ $hyper_ref } ="$externalReference$intHrefMrk$hyper_ref";
1581 #------------------------------
1582 # Remember internal HREF's not
1583 # already seen for target-tt.
1584 #------------------------------
1585 if( not is_member( $hyper_ref, \@nm_ref ) ) {
1586 push @nm_ref, $hyper_ref;
1590 #-----------------------------------------------------------------
1591 # Put out the HTML title and then suppress it for later processing
1592 #-----------------------------------------------------------------
1593 print CONVERT "<TITLE>$this_title</TITLE>\n" unless $title++;
1594 $data[$i] = ".. <$head> " . $data[$i] . " </$head>";
1597 #-------------------------------------------------------------------------------
1601 #---------------------------------------
1602 # Turn all "~text~" into "<I>text</I>"
1603 #---------------------------------------
1604 s#$italic_tt#${lt}I${gt}$1${lt}/I${gt}#g;
1607 #-------------------------------------------------------------------------------
1612 print CONVERT "<P>\n" unless $fold++;
1616 #-------------------------------------------------------------------------------
1620 s/$line_tt/${lt}P${gt}${lt}HR${gt}/;
1621 print CONVERT html_finishing( $_ ), "\n";
1624 #-------------------------------------------------------------------------------
1631 #-------------------------------------------------------------------------------
1635 my $hdr_level = shift;
1637 print CONVERT "<H$_</H$hdr_level>\n";
1640 #-------------------------------------------------------------------------------
1644 check_target_reference( $_ );
1645 /$target_tt/ && do { ($a = $4) =~ s,_, ,go; s/$target_tt/ $a/; };
1648 #-------------------------------------------------------------------------------
1650 #-----------------------------------------------------------------------------
1654 # check_target_reference( $_ );
1655 # /$target_tt/ && do { ($a = $4) =~ s,_, ,go; s/$target_tt/$a/; };
1656 # /$title_tt/i && do { print CONVERT $1, &html_finishing($2), $3, "\n"; };
1658 #-----------------------------------------------------------------------------
1661 my $titleHolder = $_;
1664 /$target_tt/ && do { ($a = $4) =~ s,_, ,go; s/$target_tt/$a/; };
1666 if( /$title_tt/i ) # this is the new title-tt from html_init
1668 $frontMrk = $1; $thisTitle = $2; $backMrk = $3;
1670 if( not $separate_html_files or $veryFirstTime )
1672 check_target_reference( $titleHolder );
1673 print CONVERT $frontMrk, &html_finishing($thisTitle), $backMrk, "\n";
1676 elsif( $frontMrk eq "<H1>" )
1678 $savedTitle = $thisTitle;
1679 $savedTitleHolder = $titleHolder;
1683 #--------------------------
1684 # Create another HTML file?
1685 #--------------------------
1686 $hyper_ref = $thisTitle;
1687 $hyper_ref =~ s/$trim_spaces/$2/o;
1688 $hyper_ref =~ s/ /_/go;
1689 $association = $MenuNames{ $hyper_ref };
1691 if( $association ne "" )
1693 $assocLevel = substr( $association, 0, 1 );
1694 $association = substr( $association, 1 );
1696 if( $converted_file ne "$association.html" )
1698 #-----------------------------
1699 # Finish off the current file.
1700 #-----------------------------
1701 print CONVERT "</BODY>\n</HTML>\n";
1704 #-----------------------------------------------------
1705 # This realigns title after nested sublevels complete.
1706 #-----------------------------------------------------
1707 if ( $assocLevel == 0 ) {
1708 $savedTitle = $thisTitle;
1711 $converted_file = "$association.html";
1712 open CONVERT, ">$converted_file" or die "Can't create $converted_file, $OS_ERROR";
1713 print CONVERT "<HTML>\n<HEAD>\n";
1714 print CONVERT "</HEAD>\n";
1715 print CONVERT "<TITLE>$savedTitle</TITLE>\n";
1716 print CONVERT "<BODY>\n";
1718 #--------------------------------------------
1719 # This puts target reference in correct file.
1720 #--------------------------------------------
1721 if( $savedTitleHolder )
1723 check_target_reference( $savedTitleHolder );
1724 if( $savedTitleHolder =~ /$title_tt/i )
1726 print CONVERT $1, &html_finishing($2), $3, "\n";
1728 $savedTitleHolder = "";
1733 check_target_reference( $titleHolder );
1734 print CONVERT $frontMrk, &html_finishing($thisTitle), $backMrk, "\n";
1739 #-------------------------------------------------------------------------------
1741 sub html_underline_tt
1743 #--------------------------------------------
1744 # Turn all "_text_" into "<I><U>text</U></I>"
1745 # Remembering to substitute intervening
1746 # underlines with spaces.
1747 #--------------------------------------------
1749 ($text = $1) =~ s,_, ,go;
1750 "${lt}I${gt}${lt}U${gt}$text${lt}/U${gt}${lt}/I${gt}"; #eg;
1753 #-------------------------------------------------------------------------------
1754 # setext to NEdit HELP conversion call-back routines.
1755 # ( in alphabetical order )
1756 #-------------------------------------------------------------------------------
1760 #----------------------------------------------------
1761 # Turn all "**text**" into "<stlMrk_B>text<stlMrk_B>"
1762 #----------------------------------------------------
1763 s#$bold_tt#${stlMrk}$TKN_BOLD$1${stlMrk}$TKN_BOLD$2#g;
1766 #-------------------------------------------------------------------------------
1768 sub help_bullet_tt { s/$bullet_tt/ * $1/ }
1770 #-------------------------------------------------------------------------------
1774 #------------------------------------------------------
1775 # The following is here to help us generate conditional
1776 # compilation elements for the 'C' compiler.
1777 #------------------------------------------------------
1778 if( /$passthru_tt/ )
1780 s/$passthru_tt//o; # remove typotag and pass line out as is.
1786 #-------------------------------------------------
1787 # This seems to be the only good place to take
1788 # care of style changes that have occurred between
1789 # usage of proportional and fixed font styles.
1790 #-------------------------------------------------
1793 $_ = $styleMark . get_style_name( $crntStyle ) . $_;
1797 my $finishedLine = help_finishing( $_ );
1799 print HELP "\"", $finishedLine, "\",\n";
1801 #----------------------------------------------------------------
1802 # To minimize newline output for the empty line elements,
1803 # the algorithm remembers if its last line had a newline emitted.
1804 #----------------------------------------------------------------
1805 $newLinePresentInLastLine = $finishedLine =~ /\\n$/;
1809 #-------------------------------------------------------------------------------
1813 #-------------------------------------------------------------------------------
1819 #----------------------------
1820 # When finishing a heading...
1821 #----------------------------
1824 #--------------------------------------------------
1825 # ... destroy any styles inadvertantly placed there
1826 #--------------------------------------------------
1829 my @line = split $stlMrk;
1830 $_ = join '', @line;
1833 #------------------------------------
1834 # ... because only one style allowed.
1835 #------------------------------------
1836 $stlFront = $styleMark . get_style_name( "" );
1838 $stlEnd = $styleMark . get_style_name( $initialStyle );
1839 $stlFront = "" if /^$styleToken/ ; # remove redundancy when present
1840 $_ = $stlFront . $_ .$stlEnd;
1843 #---------------------------------------------
1844 # Any style markers found in the current line?
1845 #---------------------------------------------
1848 #----------------------------------------
1849 # Break line up into style word elements.
1850 #----------------------------------------
1852 my @line = split $stlMrk;
1854 foreach $element ( @line )
1856 #--------------------------------------------------
1857 # Extract word emphasis token and associated words.
1858 # Embed style marker into text line.
1859 #--------------------------------------------------
1860 $element =~ /^($aStyleToken)?(.*)$/o && do {
1862 $token = ($1) ? $1 : $TKN_TEXT; # $TKN_xxx
1864 my $nextStyle = get_style( $crntStyle, $token );
1866 if( $crntStyle eq $nextStyle )
1872 $stlNm = get_style_name( $nextStyle );
1873 $line .= "$styleMark$stlNm$words";
1874 $crntStyle = $nextStyle;
1882 recover_extractions();
1885 #-------------------------------------------
1886 # Apply any initial style change introduced.
1887 #-------------------------------------------
1888 $_ = $newLeadStyle . $_;
1891 #----------------------------------------------------------------
1892 # Add newline element to all lines which are not being currently
1893 # formatted into a flowing paragraph. It is done here because the
1894 # character also has to get included in the character counts.
1895 #----------------------------------------------------------------
1896 $_ .= get_newline( 1 ) if $crnt_state ne $FMT;
1898 #----------------------------------------------------------------------
1899 # Since 2 characters (\ and n) are occupying the space of one newline,
1900 # we need to subract out the number of new lines from the total offset.
1901 #----------------------------------------------------------------------
1902 my $styleCount = count( $styleToken, $_ );
1903 my $newLineCount = count( "\\\\n", $_ );
1904 my $quoteCount = count( '"', $_ );
1905 my $backslashCount = count( "\\\\", $_ ) - $styleCount -
1906 $newLineCount - $quoteCount;
1908 my $adjustment = ($styleCount * $styleTokenSize) +
1909 ($backslashCount / 2) + $newLineCount + $quoteCount;
1911 #-----------------------------------------------------------
1912 # Now keep a running total of how many characters to emit.
1913 # (Keep 2 forms, total number for compiler string length
1914 # considerations, and another for target-tt section offsets.
1915 #-----------------------------------------------------------
1916 $sectionCharacterCnt += length( $_ );
1917 $targetOffset += length( $_ ) - $adjustment;
1922 #-------------------------------------------------------------------------------
1924 sub help_fixed_styles
1926 #----------------------------------------------------------------
1927 # All proportional styles in the style state transition table
1928 # begin with the "_" character. If we are already in the
1929 # proportional styles arena, a link, or header, no change occurs.
1930 #----------------------------------------------------------------
1931 if( $crntStyle =~ /^_/ )
1933 $crntStyle =~ s/^_//o;
1934 $styleChanged = $crntStyle unless $styleChanged;
1938 #-------------------------------------------------------------------------------
1942 my ( $text, $stlNm, $h );
1944 #--------------------------------------------------
1945 # After finding a hot-tt, substitute all underlines
1946 # with spaces and check to see if the hot-tt had
1947 # a corresponding hypertext reference. Make it
1948 # unadorned text when no reference found.
1949 #--------------------------------------------------
1951 ($text = $1) =~ s,_, ,go;
1952 $h = is_known_link( $text );
1953 $stlNm = get_style_name( $crntStyle );
1955 $h ? "$stlMrk$TKN_LINK$text$stlMrk$TKN_LINK"
1960 #-------------------------------------------------------------------------------
1966 s/$indent_tt/$1/; # get rid of indent-tt characters
1967 /\S$/ && do { $_ .= ' ' }; # make sure space available for remaining
1968 } # text in this kind of paragraph
1971 #-------------------------------------------------------------------------------
1977 enter_pre => "help_fixed_styles",
1978 leave_pre => "help_proportional_styles",
1980 enter_quote => "help_fixed_styles",
1981 leave_quote => "help_proportional_styles",
1984 #--------------------------------------------
1985 # Global elements needed for making menu code
1986 #--------------------------------------------
1989 $copy_right_holder = "Mark Edel";
1990 $hlptxt = "help_data$helpSuffix.h"; # name of file holding help data structures
1991 $hlphdr = "help_topic$helpSuffix.h"; # name of file holding help definitions
1992 $stlMrk = "\01"; # this is the character code
1993 $styleMark = '\01'; # this is the text string
1994 $styleToken = "\\$styleMark"; # this for splitting strings on styleMark
1995 $styleTokenSize = length( $styleToken ); # accounts for '\01A'
1996 $illegal_help = "HELP_none";
1998 $menu_record = "(.),(.*),(.*),(\\d)";
1999 $tgtIndx = 0; # target-tt index for hypertext reference array (@href)
2001 #-------------------------------------------------------------------
2002 # The following data is used to embed style data into the help text.
2003 #-------------------------------------------------------------------
2005 # TOKENS => text bold italic underline
2010 plain => { style => "A", states => [ "plain", "bold", "italic", "u_plain" ] },
2011 bold => { style => "B", states => [ "bold", "plain", "b_ital", "u_bold" ] },
2012 italic => { style => "C", states => [ "italic", "b_ital", "plain", "u_italic" ] },
2013 b_ital => { style => "D", states => [ "b_ital", "italic", "bold", "u_b_ital" ] },
2015 u_plain => { style => "E", states => [ "u_plain", "u_bold", "u_italic", "plain" ] },
2016 u_bold => { style => "F", states => [ "u_bold", "u_plain", "u_b_ital", "bold" ] },
2017 u_italic => { style => "G", states => [ "u_italic", "u_b_ital", "u_plain", "italic" ] },
2018 u_b_ital => { style => "H", states => [ "u_b_ital", "u_italic", "u_bold", "bold_ital" ] },
2020 # proportional font styles
2022 _plain => { style => "I", states => [ "_plain", "_bold", "_italic", "_u_plain" ] },
2023 _bold => { style => "J", states => [ "_bold", "_plain", "_b_ital", "_u_bold" ] },
2024 _italic => { style => "K", states => [ "_italic", "_b_ital", "_plain", "_u_italic" ] },
2025 _b_ital => { style => "L", states => [ "_b_ital", "_italic", "_bold", "_u_b_ital" ] },
2027 _u_plain => { style => "M", states => [ "_u_plain", "_u_bold", "_u_italic", "_plain" ] },
2028 _u_bold => { style => "N", states => [ "_u_bold", "_u_plain", "_u_b_ital", "_bold" ] },
2029 _u_italic => { style => "O", states => [ "_u_italic", "_u_b_ital", "_u_plain", "_italic" ] },
2030 _u_b_ital => { style => "P", states => [ "_u_b_ital", "_u_italic", "_u_bold", "_bold_ital" ] },
2032 # hyperLink style => "Q",
2034 # header1 style => "R", --
2035 # header2 style => "S", |_ MAX_HEADER
2036 # header3 style => "T", --
2039 #-----------------------------------------------------------
2040 # The link index is the position in a font style table
2041 # where the linking font will reside. It appears immediately
2042 # after the styles from the table above.
2043 #-----------------------------------------------------------
2044 $linkIndex = scalar( keys %styles_stt );
2045 $maxTokens = scalar( @{ $styles_stt{plain}{states} } );
2047 $STYLE_PLAIN = $styles_stt{plain}{style};
2048 $STYLE_LINK = "Q"; # link style marker, a continuation from style table
2049 $STYLE_HDR = "R"; # beginning of header style markers
2050 $MAX_HEADER = 3; # the maximum number of header styles in use
2052 $TKN_TEXT = 0; # used in style state transition, order important
2053 $TKN_BOLD = 1; # used in style state transition, order important
2054 $TKN_ITALIC = 2; # used in style state transition, order important
2055 $TKN_ULINE = 3; # used in style state transition, order important
2058 $aStyleToken = "[$TKN_TEXT$TKN_BOLD$TKN_ITALIC$TKN_ULINE$TKN_LINK]";
2060 $initialStyle = "_plain"; # the initial style for help text.
2061 $crntStyle = $initialStyle;
2064 print_menu( $crntMenu, "" ) if $print_menu; # sort of debug info
2066 #----------------------------------
2067 # Create help header (help_topic.h)
2068 #----------------------------------
2069 open HLPHDR, ">$hlphdr" or die "Can't create $hlphdr, $OS_ERROR";
2070 emit_help_header( HLPHDR, $crntMenu );
2073 #-------------------------------------------
2074 # Create help text data header (help_data.h)
2075 #-------------------------------------------
2076 open HELP, ">$hlptxt" or die "Can't create $hlptxt, $OS_ERROR";
2077 emit_helpTitles( HELP, $crntMenu );
2079 collect_internal_hypertext_references( \@data );
2081 emit_helpText( HELP, $crntMenu, \@data );
2084 #-------------------------------------------------------------------------------
2088 s/$italic_tt/${stlMrk}$TKN_ITALIC$1${stlMrk}$TKN_ITALIC/g
2091 #-------------------------------------------------------------------------------
2096 $_ .= get_newline( 2 );
2097 help_emit_line() unless $fold++;
2101 #-------------------------------------------------------------------------------
2104 sub help_quote_tt {}
2106 #-------------------------------------------------------------------------------
2108 sub help_proportional_styles
2110 #----------------------------------------------------------------
2111 # All proportional styles in the style state transition table
2112 # begin with the "_" character. If we are already in the
2113 # proportional styles arena, a link, or header, no change occurs.
2114 #----------------------------------------------------------------
2115 unless( $crntStyle =~ /^_/ or
2116 $crntStyle eq "link" or
2117 $crntStyle eq "header" ) {
2119 $crntStyle = "_$crntStyle";
2120 $newLeadStyle = $styleMark . get_style_name( $crntStyle );
2124 #-------------------------------------------------------------------------------
2128 $headingLevel = shift;
2129 #----------------------------------------------------------
2130 # Heading levels for sectioning are being required to start
2131 # at level 3 (considered the first level). This keeps the
2132 # X-resources down inside NEdit. So here is the mapping.
2138 #----------------------------------------------------------
2139 $headingLevel = ($headingLevel > 2 ) ? $headingLevel - 2 : 1;
2140 $headingLevel = $MAX_HEADER if $headingLevel > $MAX_HEADER; #
2143 $crntStyle = $initialStyle;
2147 #-------------------------------------------------------------------------------
2149 sub help_target_tt { } # cannot process target-tt at this time because
2150 # calculation of the hypertext offset requires
2151 # a fully expanded text line (see help_finishing).
2155 if( /$target_tt/ and exists $href{ $4 } )
2157 my ( $text, $tgtOffset, $originalLine );
2159 #---------------------------------------------------
2160 # Have to compute target's offset into help section.
2161 # Need actual text sans styling information. Assuming
2162 # all other text replacement has already occurred.
2163 #---------------------------------------------------
2166 s/$styleToken.//g; # remove all styling markers
2168 #--------------------------------------------------------
2169 # Inside this special substitution, a computation of the
2170 # target's offset from the beginning of the section is
2171 # being computed and applied to the hyper-reference array
2172 # element which will be emitted after all text sections
2173 # have been processed.
2174 #--------------------------------------------------------
2176 ($text = $4) =~ s,_, ,go;
2177 $tgtOffset = index( $_, $text ) + $targetOffset -1;
2178 $tgtOffset = sprintf( "%6d", $tgtOffset );
2179 $href[ $tgtIndx++ ] =~ s /^0/$tgtOffset/o;
2183 #-------------------------------------------------------
2184 # Now fix hyper-references in actual line to be emitted.
2185 #-------------------------------------------------------
2189 ($text = $4) =~ s,_, ,go;
2195 #-------------------------------------------------------------------------------
2197 sub help_title {&help_emit_line}
2199 #-------------------------------------------------------------------------------
2201 sub help_underline_tt
2203 #--------------------------------------------------
2204 # Turn all "_text_" into "<stlMrk_U>text<stlMrk_U>"
2205 # Remembering to substitute intervening
2206 # underlines with spaces.
2207 #--------------------------------------------------
2209 ($text = $1) =~ s,_, ,go;
2210 "${stlMrk}$TKN_ULINE$text${stlMrk}$TKN_ULINE";
2214 #-------------------------------------------------------------------------------
2220 $howMany-- if $newLinePresentInLastLine && $howMany > 1;
2221 return '\n' x $howMany;
2224 #-------------------------------------------------------------------------------
2228 my $linkName = shift;
2230 for( $index = 0; $index < scalar( @hot_tt_links ); $index++ )
2232 $element = $hot_tt_links[ $index ];
2233 return 1 if( $hot_tt_links[ $index ] eq $linkName );
2239 #-------------------------------------------------------------------------------
2243 my $crntStyle = shift; # plain, bold, italic, etc.
2244 my $token = shift; # $TKN_xxx
2245 my $style = "header"; # assume working on header
2247 if( $headingLevel == 0 )
2249 if( $token == $TKN_LINK )
2251 if( $crntStyle eq "link" )
2253 $style = $prevStyle;
2257 $prevStyle = $crntStyle;
2263 @transitions = @{ $styles_stt{$crntStyle}{states} };
2264 $style = $transitions[ $token ];
2271 #-------------------------------------------------------------------------------
2275 my $crntStyle = shift; # plain, bold, italic, etc.
2280 $styleName = chr(ord( $STYLE_HDR )+$headingLevel-1);
2282 elsif( $crntStyle eq "link" )
2284 $styleName = $STYLE_LINK;
2288 $styleName = $styles_stt{$crntStyle}{style};
2294 #-------------------------------------------------------------------------------
2302 while( $$line < scalar( @$setext ) )
2304 $_ = $$setext[ $$line++ ];
2305 return $_ if s/$menu_element//o;
2306 return "$_, $help_code" if s/$help_element//o;
2312 #-------------------------------------------------------------------------------
2316 my $crnt_menu = shift;
2318 my ( $menuTitle, $mneumonic, $helpName, $hideit, $type );
2320 foreach $menuItem ( @$crnt_menu )
2322 if ( $menuItem =~ /$menu_record/o )
2323 { $mneumonic=$1; $menuTitle=$2; $helpName=$3; $hideit=($4) ? $4 : "" }
2325 if( $hideit eq $help_code ) {
2330 $hideit = ", ($hideit)" if $hideit;
2334 print "$type: $indent$mneumonic, $menuTitle [$helpName]$hideit\n";
2336 if( $menuItem =~ /$subMenuIndicator/o )
2338 ($menu = $menuTitle) =~ s/ /_/og;
2339 print_menu( \@$menu, "$indent " );
2344 #-------------------------------------------------------------------------------
2346 sub collect_internal_hypertext_references
2350 my ($source, $destination );
2352 while( $line < scalar( @$setext ) )
2354 $_ = $$setext[ $line++ ];
2360 if( $destination =~ /$internal_href/ )
2362 $href{ $1 } = $source;
2368 #-------------------------------------------------------------------------------
2373 my $crnt_menu = shift;
2380 emit_help_menu_text( $setext, $stream, $crnt_menu, \$line );
2382 print $stream "static char **HelpText[] = {\n$helpNameList\n};\n\n";
2384 print $stream "HelpMenu H_M [] =\n{\n";
2385 emit_help_menu( $stream, $crnt_menu, 0, 1 );
2386 print $stream "\n};\n";
2388 #------------------------------------
2389 # Emit internal hypertext references.
2390 #------------------------------------
2391 print $stream "\nHref H_R [] =\n{\n";
2393 for( $index = 0; $index < scalar( @href ); $index++ )
2395 $element = $href[ $index ];
2396 $nextone = ( $index == $#href ) ? "NULL, " : "&H_R[%2d],";
2397 printf $stream "$sep { $nextone $element }", $index+1;
2400 print $stream "\n};\n";
2402 #-----------------------------
2403 # Emit program version string.
2404 #-----------------------------
2405 $pgmVersion = $variables{ version };
2406 $pgmVersion .= '\n' . date() if $pgmVersion !~ /$neditDefaultMarker/;
2407 print $stream "\nstatic const char * NEditVersion = \"$pgmVersion\\n\";\n";
2410 #-------------------------------------------------------------------------------
2412 sub emit_help_menu_text
2416 my $crnt_menu = shift;
2419 my ( $menuTitle, $mneumonic, $helpName, $prevLine );
2421 #----------------------------------------
2422 # For every node of the menu tree...
2423 #----------------------------------------
2424 foreach $menuItem ( @$crnt_menu )
2426 if ( $menuItem =~ /$menu_record/ )
2427 { $mneumonic=$1; $helpName=$3; ($menuTitle=$2) =~ s/_//; }
2429 #---------------------------------
2430 # ... recursively expand sub-menus
2431 #---------------------------------
2432 if( $menuItem =~ /$subMenuIndicator/ )
2434 ($menu = $menuTitle) =~ s/ /_/g;
2435 emit_help_menu_text( $setext, $stream, \@$menu, $line );
2438 elsif( $mneumonic ne $separator ) # ... and not a menu separator
2440 locate_menu_text( $setext, $menuTitle, $line )
2441 or die "Unable to find \"$menuTitle\" text!";
2446 $s_e_p = ($helpNameList) ? ",\n" : "";
2447 $helpNameList .= $s_e_p . " htxt_$helpName";
2448 $sectionCharacterCnt = 0;
2451 #------------------------
2452 # ... emit help menu text
2453 #------------------------
2456 ($_,$remainder) = get_menu_text( $setext, $remainder, $line );
2460 next if /$empty_line/ and $lineNbr == 1;
2463 #--------------------------------------------------
2464 # Save all hypertext targets found in current topic
2465 #--------------------------------------------------
2466 if( /$target_tt/ and exists $href{ $4 } )
2469 $href = $href{$target};
2471 $target =~ s/_/ /go;
2472 $topic = "HELP_\U$helpName,";
2473 $nl1 = $name_length+6; # for HELP_ and comma
2476 sprintf("0, %-${nl1}.${nl1}s \"$href\", \"$target\"", $topic );
2478 push @hot_tt_links, $href; # collect for later verification.
2481 s/\\/\\\\/go; # escape backslash any where in text
2482 s/"/\\"/go; # escape embedded double quotes
2483 s/^\s*$//; # redefine whitespace as empty line
2487 print $stream "static char * htxt_$helpName [] = {\n";
2488 $styleChanged = $initialStyle; # This forces initial style out
2489 $crntStyle = $initialStyle;
2490 parse_setext( \@section );
2491 print $stream "NULL\n};\n\n";
2496 #-------------------------------------------------------------------------------
2498 sub locate_menu_text
2501 my $menuTitle = shift;
2504 $menuTitle =~ s/_//go; # removing drop key character markers
2505 $menuTitle =~ s/ /./go; # spaces could be underlines in titles
2506 $menuTitle =~ s/\(/./go; # parens are special in regex searches...
2507 $menuTitle =~ s/\)/./go; # ... here they should be ignored
2509 #-----------------------------------------------------
2510 # When the whence value is set to zero, the search
2511 # for the text that belongs with the given menu title
2512 # is started at the beginning of the file. This allows
2513 # the menu text to be in an order other than that
2514 # specified by the menu itself. This gives freedom
2515 # to the writer; inefficiency to the text processing.
2516 #-----------------------------------------------------
2517 $$line = 0 if ( $whence != 1 );
2519 while( $$line < scalar( @$setext ) )
2521 if( $$setext[ $$line++ ] =~ /$menuTitle/ )
2523 if ( $$setext[ $$line ] =~ /$subtitle_tt/ or
2524 $$setext[ $$line ] =~ /$title_tt/ )
2527 return 1; # the first line after the setext title marker
2535 #-------------------------------------------------------------------------------
2540 my $crnt_line = shift;
2543 #-------------------------------------
2544 # Skip any setext comment lines found.
2545 #-------------------------------------
2546 while( $$setext[ $$line ] =~ /$suppress_tt/ ) { $$line ++ };
2548 $crnt_line = $$setext[ $$line++ ] if $crnt_line eq "";
2550 if( $crnt_line =~ /$twobuck_tt/ ) # end of setext document?
2556 #--------------------------------------------
2557 # Have to read ahead by one line to catch the
2558 # title of the next section, or the end of
2559 # the setext document.(Eat horizontal rulers)
2560 #--------------------------------------------
2561 do { $_ = $$setext[ $$line++ ] } until not /^ --/;
2563 #--------------------------------
2564 # Look ahead again, so that an
2565 # empty last line is not emitted.
2566 #--------------------------------
2567 if( $crnt_line =~ /^\s*$/ and
2568 ($$setext[ $$line ] =~ /$subtitle_tt/o or
2569 $$setext[ $$line ] =~ /$title_tt/o or
2570 $$setext[ $$line ] =~ /$twobuck_tt/o))
2575 if( /$subtitle_tt/o or /$twobuck_tt/o )
2577 $$line = $$line - 2;
2582 return ( $crnt_line, $_ );
2585 #-------------------------------------------------------------------------------
2590 my $crnt_menu = shift;
2594 my ( $menuTitle, $mneumonic, $helpName, $hideIt );
2599 $end_index = scalar( @$crnt_menu );
2603 $nl1 = $name_length+6; # for HELP_ and comma
2604 $nl2 = $name_length+3; # for 2 double quotes and comma
2606 #----------------------------------------
2607 # For every node of the menu tree...
2608 #----------------------------------------
2609 foreach $menuItem ( @$crnt_menu )
2611 if ( $menuItem =~ /$menu_record/ )
2616 ($menuTitle=$2) =~ s/_//;
2619 #---------------------------------
2620 # ... recursively expand sub-menus
2621 #---------------------------------
2622 if( $menuItem =~ /$subMenuIndicator/ )
2624 ($menu = $menuTitle) =~ s/ /_/g;
2625 printf $stream "$sep { &H_M[%2d], $level, %-${nl1}.${nl1}s %-${nl2}.${nl2}s $hideIt, '$mneumonic', \"$menuTitle\" }",
2626 $index, "$illegal_help,", "\"$helpName\",";
2627 $index = emit_help_menu( $stream, \@$menu, $level, $index+1 );
2632 $topic = ( $mneumonic eq $separator ) ? "$illegal_help," : "HELP_\U$helpName,";
2633 $helpName = "\"$helpName\",";
2634 $nptr = ( $end_index == 1 && $level == 1 ) ? "NULL" : "&H_M[%2d]";
2636 #---------------------------
2637 # are we at end of the menu?
2638 #---------------------------
2639 if( $end_index == 1 && $level == 1 ) {
2640 print $stream "$sep { NULL, ";
2643 printf $stream "$sep { &H_M[%2d], ", $index;
2645 printf $stream "$level, %-${nl1}.${nl1}s %-${nl2}.${nl2}s $hideIt, '$mneumonic', NULL }", $topic, $helpName;
2650 $end_index-- if $level == 1;
2656 #-------------------------------------------------------------------------------
2661 my $crnt_menu = shift;
2663 emit_copyright( $stream, "$hlptxt -- Nirvana Editor help module data" );
2664 print $stream "char *HelpTitles[] = {\n";
2665 emit_help_label( $stream, $crnt_menu );
2666 print $stream " NULL\n};\n\n";
2669 #-------------------------------------------------------------------------------
2674 my $crnt_menu = shift;
2675 my ( $menuTitle, $mneumonic, $helpName );
2677 #-----------------------------------------------------------------
2678 # Emit help title/labels for only the leaf nodes of the menu tree.
2679 #-----------------------------------------------------------------
2680 foreach $menuItem ( @$crnt_menu )
2682 if ( $menuItem =~ /$menu_record/ )
2686 ($menuTitle = $2) =~ s/_//go;
2689 if( $menuItem =~ /$subMenuIndicator/ )
2691 ($menu = $menuTitle) =~ s/ /_/go;
2692 emit_help_label( $stream, \@$menu );
2694 elsif( $mneumonic ne $separator ) # ... and not a menu separator
2696 print $stream " \"$menuTitle\",\n";
2697 push @hot_tt_links, $menuTitle; # collect for later verification.
2702 #-------------------------------------------------------------------------------
2704 sub emit_help_header # populates NEdit's help_topic.h
2707 my $crnt_menu = shift;
2709 emit_copyright( $stream, "$hlphdr -- Nirvana Editor help display" );
2710 print $stream "#define MAX_HEADING $MAX_HEADER\n";
2711 print $stream "#define STL_HD $linkIndex+1\n";
2712 print $stream "#define STL_LINK $linkIndex\n";
2713 print $stream "#define STL_NM_HEADER '$STYLE_HDR'\n";
2714 print $stream "#define STL_NM_LINK '$STYLE_LINK'\n";
2715 print $stream "#define STYLE_MARKER '$styleMark'\n";
2716 print $stream "#define STYLE_PLAIN '$STYLE_PLAIN'\n";
2717 print $stream "#define TKN_LIST_SIZE $maxTokens\n";
2719 print $stream "enum HelpTopic {\n";
2720 emit_help_topic( $stream, $crnt_menu );
2721 print $stream " HELP_LAST_ENTRY,\n";
2722 print $stream " $illegal_help = 0x7fffffff /* Illegal topic */ \n";
2723 print $stream "};\n";
2725 print $stream "#define NUM_TOPICS HELP_LAST_ENTRY\n";
2729 #-------------------------------------------------------------------------------
2734 my $crnt_menu = shift;
2735 my ( $menuTitle, $mneumonic, $helpName );
2737 #-----------------------------------------------------------------
2738 # Emit help topic name for only the leaf nodes of the menu tree.
2739 #-----------------------------------------------------------------
2740 foreach $menuItem ( @$crnt_menu )
2742 if ( $menuItem =~ /$menu_record/ )
2746 ($menuTitle = $2) =~ s/_//go;
2749 if( $menuItem =~ /$subMenuIndicator/ )
2751 ($menu = $menuTitle) =~ s/ /_/go;
2752 emit_help_topic( $stream, \@$menu );
2754 elsif( $mneumonic ne $separator ) # ... and not a menu separator
2756 print $stream " HELP_\U$helpName,\n";
2761 #-------------------------------------------------------------------------------
2766 my $filename = shift;
2768 my $year = date("y");
2769 my $padlen1 = 76 - length( $filename );
2770 my $padlen2 = 52 - length( $copy_right_holder );
2772 my $pad1 = substr( $blanks, 0, $padlen1 );
2773 my $pad2 = substr( $blanks, 0, $padlen2 );
2775 print $stream "/*******************************************************************************\n";
2776 print $stream "* *\n";
2777 print $stream "* $filename$pad1 *\n";
2778 print $stream "* *\n";
2779 print $stream " Generated on " . date() . " (Do NOT edit!)\n";
2780 print $stream " Source of content from file $setext_file\n";
2781 print $stream "* *\n";
2782 print $stream "* Copyright (c) 1999-$year $copy_right_holder$pad2 *\n";
2783 print $stream "* *\n";
2784 print $stream "* This is free software; you can redistribute it and/or modify it under the *\n";
2785 print $stream "* terms of the GNU General Public License as published by the Free Software *\n";
2786 print $stream "* Foundation; either version 2 of the License, or (at your option) any later *\n";
2787 print $stream "* version. *\n";
2788 print $stream "* *\n";
2789 print $stream "* This software is distributed in the hope that it will be useful, but WITHOUT *\n";
2790 print $stream "* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *\n";
2791 print $stream "* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *\n";
2792 print $stream "* for more details. *\n";
2793 print $stream "* *\n";
2794 print $stream "* You should have received a copy of the GNU General Public License along with *\n";
2795 print $stream "* software; if not, write to the Free Software Foundation, Inc., 59 Temple *\n";
2796 print $stream "* Place, Suite 330, Boston, MA 02111-1307 USA *\n";
2797 print $stream "* *\n";
2798 print $stream "* Nirvana Text Editor *\n";
2799 print $stream "* September 10, 1991 *\n";
2800 print $stream "* *\n";
2801 print $stream "* Written by $copy_right_holder *\n";
2802 print $stream "* *\n";
2803 print $stream "*******************************************************************************/\n";
2808 #-------------------------------------------------------------------------------
2815 Setext - convert Structured Enhanced TEXT into HTML or plain text.
2819 Usage: setext [ -dhHStTV ][-c conditional] \
2820 [-v name=value][setext_file [converted_file]]
2822 setext {-mp} [-c conditional][-M menuSuffix] \
2823 [-v name=value] setext_file
2825 The first form of setext is used to convert Structure Enhanced TEXT
2826 documents into HTML or simple text documents. The second form is
2827 specific to generating the Nirvana Editor (NEdit) help menu code
2828 from a setext document with Menu and Help directives.
2830 -c conditional text definitions, separated by commas.
2831 -d do not automatically make titles hypertext references (HTML only)
2832 -h show this usage clause.
2833 -H convert setext_file to HyperText Markup Language (HTML).
2834 -m generate NEdit help menu code files.
2835 -M name NEdit help menu code files using this suffix.
2836 -p do option -m and print out NEdit help elements.
2837 -S convert setext_file into separate HTML files.
2838 -t convert setext_file to simple text (default).
2839 -T emit setext typotag definitions in use.
2840 -v defines variable name and assigns it the given value.
2841 (more than one occurrence of -v can be made) The variables
2842 are made available for use within the setext document parsing.
2843 -V display the version of this setext script.
2847 This Structured Enhanced TEXT converter produces either HTML or plain
2848 text files from a given setext source. The HTML files produced can
2849 include hypertext references to within itself, or to external
2850 destinations. The setext converter also has the capability of providing
2851 different content in the resulting output files through a conditional
2852 text mechanism, and variable data definitions. All this allows a
2853 publisher to maintain a single, very readable, source while producing
2854 varying content for different output formats and audiences.
2856 When the converted_file argument is missing, STDOUT is used.
2857 When the setext_file argument is missing, STDIN is used. This gives
2858 setext the capability of being a filter to other programs.
2860 To get conditional text within a setext document to be displayed,
2861 supply a definition tag through the -c option. For example,
2863 setext -c NEDITDOC help.etx nedit.doc
2865 Would generate a plain text document, nedit.doc, from the source
2866 help.etx, including/excluding text marked with 'NEDITDOC'
2867 conditional text markers, also known as 'maybe' typotags.
2869 Use the -T option to see the set of typotags supported by this
2870 converter. Further explanations of typotags occurs there.
2872 =head2 NEdit Help Menu
2874 When generating the NEdit help menu code, two files will be produced,
2875 help_data.h and help_topic.h (when the -M option is not used).
2876 These two files contain all the programmatic
2877 data needed to implement hypertext menus within the NEdit program.
2878 The following is an example of a setext invocation which assumes that
2879 the variable 'version' is being used within the help.etx file.
2881 setext -m -v "version=6.0" help.etx
2883 If the -M option is used, its value is appended to the root portion
2884 of the two generated files. For example,
2886 setext -m -c VMS -M _VMS help.etx
2888 will generate the files help_topic_VMS.h and help_data_VMS.h. The
2889 conditional portion of the help menu specifically designated for VMS
2890 will be extracted from the help.etx source.
2892 Below is what is used to guide the generation of 'C'-Motif menus.
2893 Indentation is SIGNIFICANT in the "Menu" directive lines below. It
2894 is used to determine under which menu element another item will belong.
2895 The number of spaces indented is not significant, but items to be placed
2896 in the same menu panel MUST line up at the same indent level.
2897 ALL nodes of this menu "tree" should have help name qualifiers.
2898 These are used to produce the internal lists used by NEdit help code.
2900 By default, the first character of the menu element will be used as a
2901 menu mneumonic key. To use another character in the menu element for
2902 this purpose, surround the character with underscores (eg. I w_a_nt 'a').
2904 The menu title MUST match the one found in the actual help text (sans
2905 special mneumonic key character marking). The help text title may include
2906 underlines (for spaces) when it is a hyperlink target.
2908 The Help-name is used to generate various data structure names. For
2909 instance, the 'start' help name will be used to generate the HelpTopic
2910 enumeration value HELP_START and the character array htxt_start which
2911 holds the actual help text used in the menu dialogs. Consequently, these
2912 names need to be unique and contain only the characters that a 'C'
2913 compiler can digest.
2915 Menu separator lines use a dash (-) character for the Menu Title. They
2916 should also have a unique Help-name.
2918 A numerical value following the Help-name (separated from the name by
2919 a comma and/or spaces) is part of a menu element hiding scheme implemented
2920 in buildHelpMenu (found in 'menu.c'). When the number matches the hideIt
2921 value found in the procedure, that element will effectively become invisible.
2922 This mechanism was created for particular menu features that are not
2923 available to all incarnations of NEdit (in this case, the VMS version).
2925 A "Help" directive is used for all other text used as NEdit help, but
2926 does not show up in the Help menu. The following is a sample of
2927 Menu and Help directives.
2929 .. Menu Title # Help-name
2930 .. ------------------------------------------------------------
2931 .. Menu: Getting Started # start
2932 .. Menu: Basic Operation # basicOp
2933 .. Menu: Selecting Text # select
2934 .. Menu: Finding and Replacing Text # search
2935 .. Menu: Cut and Paste # clipboard
2936 .. Menu: Using the Mouse # mouse
2937 .. Menu: Keyboard Shortcuts # keyboard
2938 .. Menu: S_h_ifting and Filling # fill
2939 .. Menu: F_i_le Format # format
2941 .. Menu: Features for Programming # features
2942 .. Menu: Programming with NEdit # programmer
2943 .. Menu: Tabs/Emulated Tabs # tabs
2944 .. Menu: Auto/Smart Indent # indent
2945 .. Menu: Syntax Highlighting # syntax
2946 .. Menu: Finding Declarations (ctags) # tags
2948 .. Menu: Regular Expressions # regex
2949 .. Menu: Basic Syntax # basicSyntax
2950 .. Menu: Metacharacters # escapeSequences
2951 .. Menu: Parenthetical Constructs # parenConstructs
2952 .. Menu: Advanced Topics # advancedTopics
2953 .. Menu: Examples # examples
2955 .. Menu: Macro/Shell Extensions # extensions
2956 .. Menu: Shell Commands and Filters # shell, 1
2957 .. Menu: Learn/Replay # learn
2958 .. Menu: Macro Language # macro_lang
2959 .. Menu: M_a_cro Subroutines # macro_subrs
2960 .. Menu: Action Routines # actions
2962 .. Menu: Customizing # customizing
2963 .. Menu: Customizing NEdit # customize
2964 .. Menu: Preferences # preferences
2965 .. Menu: X Resources # resources
2966 .. Menu: Key Binding # binding
2967 .. Menu: Highlighting Patterns # patterns
2968 .. Menu: Smart Indent Macros # smart_indent
2970 .. Menu: NEdit Command Line # command_line
2971 .. Menu: Client/Server Mode # server
2972 .. Menu: Cr_a_sh Recovery # recovery
2973 .. Menu: ---------------------------------- # separator1
2974 .. Menu: Version # version
2975 .. Menu: Distribution Policy # distribution
2976 .. Menu: Mailing _L_ists # mailing_list
2977 .. Menu: Problems/Defects # defects
2978 .. ------------------------------------------------------------
2979 .. Help: Tabs Dialog # tabs_dialog