]> git.donarmstrong.com Git - lib.git/blob - emacs_el/tiny-tools/tiny/tinytf.el
add tiny-tools
[lib.git] / emacs_el / tiny-tools / tiny / tinytf.el
1 ;;; tinytf.el --- Document layout tool for (T)echnical text (F)ormat
2
3 ;; This file is not part of Emacs
4
5 ;;{{{ Id
6
7 ;; Copyright (C)    1997-2007 Jari Aalto
8 ;; Keywords:        wp
9 ;; Author:          Jari Aalto
10 ;; Maintainer:      Jari Aalto
11 ;;
12 ;; To get information on this program, call M-x tinytf-version.
13 ;; Look at the code with folding.el.
14
15 ;; COPYRIGHT NOTICE
16 ;;
17 ;; This program is free software; you can redistribute it and/or modify it
18 ;; under the terms of the GNU General Public License as published by the Free
19 ;; Software Foundation; either version 2 of the License, or (at your option)
20 ;; any later version.
21 ;;
22 ;; This program is distributed in the hope that it will be useful, but
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25 ;; for more details.
26 ;;
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with program; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
30 ;; Boston, MA 02110-1301, USA.
31 ;;
32 ;; Visit <http://www.gnu.org/copyleft/gpl.html> for more information
33
34 ;;}}}
35 ;;{{{ Install
36
37 ;; ....................................................... &t-install ...
38 ;; Put this file on your Emacs-Lisp load path, add following into your
39 ;; ~/.emacs startup file.
40 ;;
41 ;;      (add-hook 'tinytf-:load-hook 'turn-on-tinytf-mode-all-buffers)
42 ;;      (setq tinytf-:mode-prefix-key "z")   ;; faster than default C-c C-z
43 ;;      (require 'tinytf)
44 ;;
45 ;; or autoload and your Emacs starts faster, preferred method:
46 ;;
47 ;;      (setq tinytf-:mode-prefix-key "z")
48 ;;      (autoload 'tinytf-mode                 "tinytf" "" t)
49 ;;      (autoload 'turn-on-tinytf-mode-maybe   "tinytf" "" t)
50 ;;
51 ;; To use additional function keys, add this line:
52 ;;
53 ;;      (setq tinytf-:mode-define-keys-hook
54 ;;        '(tinytf-mode-define-keys tinytf-mode-define-f-keys)))
55 ;;
56 ;; Additional hooks to detect and format buffer (optional):
57 ;;
58 ;;       (add-hook 'write-file-hooks 'tinytf-untabify-buffer)
59 ;;       (add-hook 'find-file-hooks 'turn-on-tinytf-mode-maybe)
60 ;;
61 ;; If you feel that you have to redefine some binding to suit your
62 ;; keyboard better, please do add similar setup to your emacs
63 ;;
64 ;;      (add-hook 'tinytf-:mode-define-keys-hook 'my-tinytf-mode-define-keys)
65 ;;
66 ;;      (defun my-tinytf-mode-define-keys ()
67 ;;        (let ((map tinytf-:mode-prefix-map))
68 ;;          (tinytf-mode-define-keys)   ;;  Default keys.
69 ;;          (tinytf-mode-define-f-keys)
70 ;;          (define-key map "]"  'tinytf-mark-word-sample)
71 ;;          (define-key map "["  'ignore)
72 ;;          (define-key map "{"  'tinytf-mark-word-emp)
73 ;;          (define-key map "}"  'tinytf-mark-word-strong)))
74 ;;
75 ;; To make HTML, you need conversion Perl script *t2html.pl* available at
76 ;; http://perl-text2html.sourceforge.net/
77 ;;
78 ;; It is possible to write documentation into other files as well
79 ;; using TF format. There is another perl program that can extract the
80 ;; documentation into text/plain by omitting comments:
81 ;;
82 ;;      http://cpan.perl.org/modules/by-authors/id/J/JA/JARIAALTO/
83 ;;      ripdoc.pl
84 ;;
85 ;; For example this lisp file's documentation can be converted into HTML
86 ;; with following command sequence:
87 ;;
88 ;;      % ripdoc.pl tinytf.el | t2html.pl > tinytf.html
89 ;;
90 ;; If you have any questions use this function to contact maintainer
91 ;;
92 ;;      M-x tinytf-submit-bug-report
93
94 ;;}}}
95
96 ;;{{{ Documentation
97
98 ;; ..................................................... &t-commentary ...
99 ;;; Commentary:
100
101 ;;  Preface, Jan 1997
102 ;;
103 ;;      Late in the 1996 there was a need for a better text file
104 ;;      handling than just plan `text-mode'. I was looking for a simple
105 ;;      tool to generate HTML pages out of text-based documents. After some
106 ;;      researching on the web, I still couldn't find anything that would
107 ;;      have been strictly a text-based solution. There were many "languages"
108 ;;      from which the HTML could be generated, but really, I didn't want
109 ;;      to learn any new language just for that. I can understand people
110 ;;      that write their documents still using LaTeX, but Win32 Word
111 ;;      is much suitable and more known than any of those exotic formats.
112 ;;      The project started by creating the tool that converted text into
113 ;;      HTML (Perl *t2html.pl* script) and then writing a Emacs package to
114 ;;      help writing the text files. It has been proven to be really nice
115 ;;      combination where flexibility meets cross-platform demands.
116 ;;
117 ;;  Overview of features
118 ;;
119 ;;      You can use `M-x' `add-change-log-entry-other-window' (C-x 4 a) to
120 ;;      create a standard ChangeLog record for your changes under the
121 ;;      headings.
122 ;;
123 ;;      The text layout you write
124 ;;
125 ;;      o   You write text in rigid format called 'Technical'
126 ;;      o   There are only two heading levels, one at column 0, and
127 ;;          another at column 4. NO OTHER SUB-HEADINGS SUPPORTED.
128 ;;      o   Text is written at column 8, at the first standard tab position.
129 ;;      o   Each column has different meaning how text is interpreted
130 ;;          into HTML with *t2html.pl* perl script.
131 ;;      o   The full 'Technical text format' is described in the
132 ;;          function description of `tinytf-mode'. The most recent description
133 ;;          is always described in the perl program t2html.pl --help
134 ;;      o   The is only a handful, natural, mark up conventions for PLAIN TEXT.
135 ;;          The whole idea was that you do not need to learn any
136 ;;          mark up language, but just write standard looking text, which is
137 ;;          easily managed and edited with any editor. In addition `diff(1)',
138 ;;          `patch(1)' and `cvs(1)' are the most effective tools to keep your
139 ;;          "text" document project in condition and encourage others to
140 ;;          contribute fixes to your text files.
141 ;;
142 ;;      This package
143 ;;
144 ;;      o   Can show text in outline style manner: you can open and close
145 ;;          headings.
146 ;;      o   Provides commands to move among headings easily.
147 ;;      o   Capitalizes heading with one command.
148 ;;      o   Numbers headings with one command.
149 ;;      o   Text is untabified in regular intervals.
150 ;;      o   On-line help in 19.30+. It assist you writing the text
151 ;;          by displaying message in echo area: how the text is interpreted by
152 ;;          t2html.pl program, that is, how the text would look in HTML.
153 ;;      o   Offer functions to mark text with special text MARKERS that
154 ;;          would produce <STRONG> or <EMP> and the like in the HTML.
155 ;;
156 ;;  What is Technical Format?
157 ;;
158 ;;      In short: it is list of text placement and formatting rules.
159 ;;      And you're looking at it right now in this document.
160 ;;
161 ;;      This package offers minor mode for text files and helps you to
162 ;;      maintain correct layout. You can even convert file into HTML very
163 ;;      easily with the perl script which is usually distributed in the
164 ;;      complete Tiny Tools Kit or available separately from the CPAN
165 ;;      under developer account JARIAALTO. You do not need to know a shred
166 ;;      about the HTML language itself. And it is much easier to update
167 ;;      text files, than deal with HTML itself. When you have text ready,
168 ;;      you just feed it to the t2html.pl perl script and it gives you
169 ;;      nicely formatted HTML page. Writing HTML *home* pages is different
170 ;;      story, because you usually want to include some graphics,
171 ;;      JavaScript, PHP or JSP in the page. But putting some text document
172 ;;      available in HTML format is easily made possible with this package.
173 ;;
174 ;;      In the other hand, while you may not be interested in HTML, you
175 ;;      could still consider writing your documents in 'Technical format'
176 ;;      -- with word *technical* I refer to the layout of the text, which
177 ;;      is very _rigid_. In order to use facilities in this package,
178 ;;      e.g. heading hiding/showing, the headings must be placed in
179 ;;      columns 0 and 4 and the first word must be in *uppercase*.  The
180 ;;      actual text you write starts at column 8.
181 ;;
182 ;;      If you decide write text like this, you become accustomed to the
183 ;;      layout very quickly and it also helps keeping your documents in
184 ;;      the same format.
185 ;;
186 ;;      All in all, this package was primarily designed to help writing
187 ;;      text documents for t2html.pl and viewing document in *outline*
188 ;;      styled selective display. Please refer to mode description for
189 ;;      full details of the text layout format.
190 ;;
191 ;;  TF described briefly
192 ;;
193 ;;      Please note, that this section may be slightly out of date.
194 ;;      You should read up to date information from the conversion
195 ;;      program using command `t2html.pl' `--help' available at
196 ;;      http://perl-text2html.sourceforge.net/ and nearest Perl CPAN
197 ;;      http://cpan.perl.org/modules/by-authors/id/J/JA/JARIAALTO/
198 ;;
199 ;;      --//-- TF description start
200 ;;
201 ;;      0123456789 123456789 123456789 123456789 123456789 column numbers
202 ;;
203 ;;      Table of contents
204 ;;
205 ;;              <Do not write any text inside this heading. It will>
206 ;;              <be generated by tinytf.el automatically with M-x tinytf-toc>
207 ;;
208 ;;      Heading 1 starts from left
209 ;;
210 ;;       emphatised text at column 1,2,3
211 ;;
212 ;;
213 ;;          This is heading 2 at column 4, started with big letter
214 ;;
215 ;;              Standard text starts at column 8, you can
216 ;;              *emphatize* text or make it _strong_ and show
217 ;;              variable name like =ThisVariableSample=. notice that
218 ;;              `ThisIsAlsoVariable' and you can even _*nest*_ the mark up.
219 ;;              more txt in this paragraph txt txt txt txt txt txt txt txt
220 ;;              txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt
221 ;;              txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt
222 ;;
223 ;;           Plain but colored text at columns 5, 6
224 ;;
225 ;;             EMPhatised text starts at column 7, Like heading level 3
226 ;;
227 ;;             "Special STRONG EMP text in column 7 starts with double quote"
228 ;;
229 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
230 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
231 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
232 ;;
233 ;;               strong text at columns 9 and 11
234 ;;
235 ;;                Column 10 has quotation text
236 ;;                Column 10 has quotation text
237 ;;                Column 10 has quotation text
238 ;;
239 ;;                  Column 12 is reserved for code examples
240 ;;                  Column 12 is reserved for code examples
241 ;;                  All text here are surrounded by SAMP codes
242 ;;
243 ;;          Heading 2, at column 4 again
244 ;;
245 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
246 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
247 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
248 ;;
249 ;;              o   Bullet 1 txt txt txt txt txt txt txt txt
250 ;;                  ,txt txt txt txt txt txt txt txt
251 ;;
252 ;;                  Notice that previous paragraph ends to P-comma code,
253 ;;                  it tells this paragraph to continue in bullet
254 ;;                  mode, otherwise this column at 12 would be
255 ;;                  interpreted as SAMPLE code.
256 ;;
257 ;;              o   Bullet 2, text starts at column 12
258 ;;              o   Bullet 3. Bullets are advised to keep together
259 ;;              o   Bullet 4. Bullets are advised to keep together
260 ;;
261 ;;              .   This is ordered list nbr 1, text starts at column 12
262 ;;              .   This is ordered list nbr 2
263 ;;              .   This is ordered list nbr 3
264 ;;
265 ;;              .This line uses BR code, notice the DOT-code at beginning
266 ;;              .This line uses BR code
267 ;;              .This line uses BR code
268 ;;
269 ;;             "This is emphatized text starting at column 7"
270 ;;              .And this text is put after the previous line with BR code
271 ;;             "This starts as separate line just below previous one, EM"
272 ;;              .And continues again as usual with BR code
273 ;;
274 ;;              See the document #URL-BASE/document.txt, where #URL-BASE
275 ;;              tag is substituted with -base switch contents.
276 ;;
277 ;;              Make this email address clickable <foo\@site.com>
278 ;;              Do not make this email address clickable -<bar\@site.com>,
279 ;;              because it is only an example and not a real address.
280 ;;              Noticed the minus(-) prefix at the beginning of url?
281 ;;
282 ;;      Heading level 1 again at column 0
283 ;;
284 ;;          Sub heading, column 4
285 ;;
286 ;;              And regular text, column 8
287 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
288 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
289 ;;              txt txt txt txt txt txt txt txt txt txt txt txt
290 ;;
291 ;;      --//-- TF description end
292 ;;
293 ;;  How do you write text
294 ;;
295 ;;      This package turns on two minor modes: `tinytab-mode', that handles
296 ;;      your TAB key movements and `tinytf-mode', the Technical format
297 ;;      minor mode. If you're uncertain about how the column will be
298 ;;      treated in HTML output, call following function. If you have 19.30+
299 ;;      this is not necessary, see note about post command above.
300 ;;
301 ;;        Do you wonder why 'z' prefix is default? Well, I wanted a fast
302 ;;        key that was mostly unused. You can change that if you prefer
303 ;;        some other key. See variable `tinytf-:mode-prefix-key'
304 ;;
305 ;;          z RET   tinytf-column-info-display
306 ;;
307 ;;      Normal text you write as usual, but if you want to mark regions
308 ;;      as "quotations" or "code examples" there is appropriate indent
309 ;;      commands
310 ;;
311 ;;          z /     tinytf-indent-region-text
312 ;;          z '     tinytf-indent-region-quote
313 ;;          z ;     tinytf-indent-region-sample
314 ;;          z :     tinytf-indent-region-strong
315 ;;
316 ;;          z t     tinytf-indent-paragraph-text
317 ;;          z a     tinytf-indent-paragraph-text-as-is
318 ;;          z l     tinytf-indent-paragraph-text-and-fill
319 ;;          z q     tinytf-indent-paragraph-quote
320 ;;          z Q     tinytf-indent-paragraph-quote-and-fill
321 ;;          z s     tinytf-indent-paragraph-sample
322 ;;          z 0     tinytf-indent-paragraph-zero
323 ;;
324 ;;      The `tinytf-indent-paragraph-text-as-is' is a bit special, because
325 ;;      it won't fill the text while it moves the paragraph to the text
326 ;;      position. Instead it adds symbolic <BR> codes to the front of every
327 ;;      moved line. In HTML this ensures that the lines will be shown
328 ;;      exactly as you see them. See also BR mark commands.
329 ;;
330 ;;      There is no functions for bullet creation, because you can write
331 ;;      them easily by hand. Use `z' `b' to fill bullet text nicely.
332 ;;      Bullets look like this
333 ;;
334 ;;          o   This is bullet..
335 ;;              and cont'd line here
336 ;;          o   Yet another bullet
337 ;;              and cont'd line here
338 ;;
339 ;;      The `tinytab-mode' will advance your tab key by 4 every time, so
340 ;;      the text in the bullets go to the right column (12). Remember also
341 ;;      to keep the `tinytab-return-key-mode' on, because that continues
342 ;;      lines as they were written above when you press return. See also
343 ;;      bullet conversion command, which reformats previous text that used
344 ;;      dashes(-) to separate bullets.
345 ;;
346 ;;          z b     tinytf-bullet-format
347 ;;
348 ;;  BR marking commands
349 ;;
350 ;;      In Html, the text would normally wrap according to the browser's
351 ;;      page width. But sometimes you may wish to tell exactly that
352 ;;      it shouldn't wrap the lines according to browser. For example
353 ;;      if you want to include a quoted text "as is" from the Usenet
354 ;;      posts to your page, you need o add symbolic BR code to the beginning
355 ;;      of each line. Like including the following quotation
356 ;;
357 ;;          >>Jim has a good point here...
358 ;;          >>I would have expected that the system depends on..
359 ;;          >Yeah; but you hadn't looked at the /usr/adm/today.log
360 ;;          >
361 ;;
362 ;;      In order to add this to your page "as is"; you can do this:
363 ;;      indent it as "Sample" and it will automatically show like that.
364 ;;      But normally you want it to show as quoted text where you refer.
365 ;;      Then you do:
366 ;;
367 ;;          z Q         tinytf-indent-paragraph-quote
368 ;;          z m b       tinytf-mark-br-paragraph
369 ;;
370 ;;      Which will prepend dot-code(.) to the front of every line.
371 ;;      You can also add the *dot-code* by yourself or use following
372 ;;      command
373 ;;
374 ;;          z m B       tinytf-mark-br-line
375 ;;
376 ;;  Heading writing and handling
377 ;;
378 ;;      You can only use 2 heading levels, which normally suffices.  Sorry,
379 ;;      there is no support for more deeper headings. You start headings
380 ;;      with big letters or number at column 0 or 4. Here is some
381 ;;      specialized commands for headings.
382 ;;
383 ;;      This one converts first character of each heading to
384 ;;      uppercase. This fixes mistakenly left lowercase letters.
385 ;;
386 ;;          z f h     tinytf-heading-fix
387 ;;
388 ;;          before command:
389 ;;          heading
390 ;;              heading
391 ;;
392 ;;          after command:
393 ;;          Heading
394 ;;              Heading
395 ;;
396 ;;      You can (re)number heading easily with following command. If
397 ;;      there is no number in the line, one is added to the beginning of
398 ;;      heading. And if you have added new heading somewhere in the
399 ;;      middle of text, just call this function and it renumbers all
400 ;;      headings again. Running command with *prefix* *argument* removes
401 ;;      numbering.
402 ;;
403 ;;          z f 0     tinytf-heading-numbering
404 ;;
405 ;;          before command:
406 ;;          heading
407 ;;              heading
408 ;;          heading
409 ;;              heading
410 ;;
411 ;;          after command:
412 ;;          1.0 heading
413 ;;              1.1 heading
414 ;;          2.0 heading
415 ;;              2.1 heading
416 ;;
417 ;;      One note about renumbering. Some people write heading number so
418 ;;      that they are closed with parenthesis. This style is not
419 ;;      recommended with technical format style and when you do renumber,
420 ;;      those parenthesis will be removed. The parenthesis style is not
421 ;;      supported because the plain number style is more easily parsed
422 ;;      and detected. In addition, the plain number style in headings is
423 ;;      more widely used in the world.
424 ;;
425 ;;          before command:
426 ;;          1.0) heading
427 ;;              1.1) heading
428 ;;
429 ;;          after command:
430 ;;          1.0 heading
431 ;;              1.1 heading
432 ;;
433 ;;
434 ;;  Heading fixing
435 ;;
436 ;;          z f a   `tinytf-fix-all'
437 ;;                  Does lot's of things. Trim away trailing blanks
438 ;;                  from buffer. Untabify buffer.
439 ;;                  Renumber headings if needed. Delete extra whitespace
440 ;;                  around headings.
441 ;;
442 ;;          z f c   `tinytf-heading-fix-case'
443 ;;                  convert current heading to lowercase
444 ;;
445 ;;          z f C   `tinytf-heading-fix-case-all'
446 ;;                  convert all heading to lowercase
447 ;;
448 ;;  About table of contents
449 ;;
450 ;;      When you write text, you don't write the table of contents, but
451 ;;      the headings. Be sure to add heading "Table of contents" somewhere
452 ;;      in the document. To generate table of contents use commands:
453 ;;
454 ;;          z T             tinytf-toc, Try with C-u argument too
455 ;;          z mouse-1       tinytf-toc-mouse
456 ;;
457 ;;  Selective display
458 ;;
459 ;;      The hiding and showing of the headings and their text is done by
460 ;;      using the outline/folding style display. There is no magic in this;
461 ;;      but there is two interesting commands that you can use in any
462 ;;      selective display buffer.
463 ;;
464 ;;          z C-p     Prints selective display (what you actually see)
465 ;;          z C-c     Copy selective display
466 ;;
467 ;;  Word about key definitions when mode is turned on
468 ;;
469 ;;      When the minor mode is active it overrides some commonly used
470 ;;      key bindings and moves their original function under Control key.
471 ;;      For example:
472 ;;
473 ;;          original PgUp    --> Now Control-PgUp
474 ;;          original PgDown  --> Now Control-PgDown
475 ;;
476 ;;          PgUp             --> Moving heading backward
477 ;;          DownUp           --> Moving heading forward
478 ;;
479 ;;      If you are using X environment or your emacs recognizes mouse,
480 ;;      then there is one handy binding that opens or closes heading
481 ;;      levels when you click over them.
482 ;;
483 ;;          [mouse-3]       tinytf-mouse-context-sensitive
484 ;;
485 ;;      If you press this mouse button anywhere else than over the
486 ;;      headings, it'll call original binding. This feature is similar as
487 ;;      what is used in folding.el
488 ;;
489 ;;  Technical note: about the outline layout
490 ;;
491 ;;      Speed was my primary goal when I added the outline code. But that
492 ;;      came with a price: I would have liked that the Heading-1 were
493 ;;      separated by at least one empty space so that the buffer would
494 ;;      look visually better.
495 ;;
496 ;;          heading1-1
497 ;;              heading1-1
498 ;;              heading1-2
499 ;;                                      << empty space here
500 ;;          heading2-1
501 ;;              heading2-1
502 ;;              heading2-2
503 ;;
504 ;;      But that would have required adding some extra code to do bound
505 ;;      checking every time the block is collapsed/opened. Currently I'm
506 ;;      not going to add that checking because it would reduce speed and
507 ;;      the check would cause unnecessary complexity to current code
508 ;;      flow.
509 ;;
510 ;;  Technical note: about the default prefix key z
511 ;;
512 ;;      The prefix key can be defined by setting `tinytf-:mode-prefix-key'
513 ;;      The default binding is `C-c` `C-z', but if you want more comfortable
514 ;;      editing, you can set it to "z". When the key is a single character,
515 ;;      the key "doubles"; i.e. pressing "zz" will generate the plain "z"
516 ;;      character.
517 ;;
518 ;;  Technical note: post command
519 ;;
520 ;;      This note is valid only for old Emacs releases, prior 20.x.
521 ;;
522 ;;      While you type text in the buffer, the post command activates at
523 ;;      regular intervals to untabify the buffer. The untabify is done
524 ;;      because it makes formatting text easier and when you print the text
525 ;;      file, you can be sure that the output is the same regardless of
526 ;;      the tabs.
527 ;;
528 ;;      If you have Emacs 19.30+ there is additional help feature available
529 ;;      to you. When you sit still in some column position for few seconds,
530 ;;      the column description will be shown automatically. That should
531 ;;      help keeping you informed of the text layout.
532 ;;
533 ;;  Technical note: HTML utilities
534 ;;
535 ;;      Two external utilities are searched for HTML generation:
536 ;;      t2html.pl and htmlize.el. If these utilities are found,
537 ;;      their locations are stored to plist of variable `tinytf-menu'.
538 ;;      See source code of function `tinytf-utility-programs-check'
539 ;;      for more.
540 ;;
541 ;;  Known bugs
542 ;;
543 ;;      In Emacs 20.6 the TinyTf pull down menu contains bold titles
544 ;;      for certain sections. This gets almost always garbled with
545 ;;      the first pull-down. Selecting the menu second time shows
546 ;;      correct section names with bold letters.
547
548 ;;}}}
549
550 ;;; Change Log:
551
552 ;;; Code:
553
554 ;;{{{ Libraries and compilation
555
556 (require 'tinylibm)
557
558 (eval-when-compile
559   (ti::package-use-dynamic-compilation)
560   ;;  Need grep-regexp-alist
561   (require 'compile))
562
563 (eval-and-compile
564   (defvar tinytab-mode            nil)
565   (defvar tinytab-:div-factor     nil)
566   ;;  Just forward declarations to shut up byte compiler.
567   (defvar font-lock-keywords)
568   (defvar font-lock-mode)
569   (defvar global-font-lock-mode)
570   (defvar grep-regexp-alist)
571   (defvar add-log-current-defun-header-regexp)
572   (autoload 'compile-internal "compile")
573   (if (or (fboundp 'htmlize-buffer)
574           (locate-library "htmlize"))
575       (autoload 'htmlize-buffer "htmlize" "" t)
576     (message "\
577   ** tinytf.el: Hm, no htmlize.el found. [you can still use this package]
578                 2001-10-10 it was at http://fly.srk.fer.hr/~hniksic/emacs/htmlize.el")))
579
580 (ti::package-defgroup-tiny TinyTf tinytf-: wp
581   "Minor mode for writing text in 'Technical text format'.
582
583       o   You write text in rigid format called 'Technical'
584       o   There are only two heading levels, one at column 0, and
585           another at column 4. NO OTHER SUB-HEADINGS SUPPORTED.
586       o   Text is written in column 8
587       o   Each column has different meaning how text is intepreted
588           into html.
589       o   The full 'Technical text format' is described in the
590           function description of `tinytf-mode'")
591
592 ;;}}}
593 ;;{{{ setup: hooks
594
595 (defcustom tinytf-:load-hook nil
596   "*Hook that is run when package is loaded."
597   :type  'hook
598   :group 'TinyTf)
599
600 (defcustom tinytf-:process-compile-hook
601   '(tinytf-compile-mode-settings)
602   "*Hook that is run when compile is called (See link check)."
603   :type  'hook
604   :group 'TinyTf)
605
606 (defcustom tinytf-:move-paragraph-hook nil
607   "*Hook run with arguments BEG END of region that was moved."
608   :type  'hook
609   :group 'TinyTf)
610
611 (defcustom tinytf-:fix-all-hook nil
612   "*Hook run when function `tinytf-fix-all' is called."
613   :type  'hook
614   :group 'TinyTf)
615
616 (defcustom tinytf-:tinytf-mode-p-function 'tinytf-text-format-file-p
617   "*Function to check if buffer is in Techical Format.
618 Function must return t or nil."
619   :type  'function
620   :group 'TinyTf)
621
622 (defcustom tinytf-:t2html-link-cache-file
623   (ti::package-config-file-prefix "tinytf-link-cache.txt")
624   "*File to contains cached OK links for the link check feature."
625   :type  'filename
626   :group 'TinyTf)
627
628 (defcustom tinytf-:buffer-file-name-html-source-function
629   'tinytf-convert-buffer-file-name-html-source
630   "*Return filename from where to read plain text.
631 For files this should be `buffer-file-name', but for buffer
632 that are not associated with file, a temporary filename shoudl be generated.
633
634 Function arguments:
635
636   buffer pointer."
637   :type  'function
638   :group 'TinyTf)
639
640 (defcustom tinytf-:buffer-file-name-html-destination-function
641   'tinytf-convert-buffer-file-name-html-destination
642   "*Return filename where the HTML is stored.
643
644 Function arguments:
645
646   buffer pointer."
647   :type  'function
648   :group 'TinyTf)
649
650 (defcustom tinytf-:binary-t2html
651   (let ((path (ti::file-path-to-unix
652                (ti::file-get-load-path "t2html.pl" exec-path))))
653     (if path
654         (message "tinytf.el: FOUND %s" path)
655       (message
656        (concat
657         "tinytf.el: ** No t2html.pl along PATH. "
658         "Visit http://perl-text2html.sourceforge.net/")))
659     path)
660   "Path to t2html.pl perl script. Do not rename t2html.pl."
661   :type  'filename
662   :group 'TinyTf)
663
664 ;;}}}
665 ;;{{{ setup: user config
666
667 (defcustom tinytf-:heading-regexp "[A-Z0-9!]"
668   "*Heading character set regexp. This charset is case sensitive.
669 If there is these characters immediately after indentation, then line
670 is a heading.
671
672 The default regexp is [A-Z0-9!], where the ! is used as a special control
673 code. The double !! signifies in the produced html
674 that there should be <hr> code before heading. Like the following.
675
676     !! This heading has HR code in the html."
677   :type  '(string :tag "Charset regexp")
678   :group 'TinyTf)
679
680 (defcustom tinytf-:heading-regexp-no-numbering "[!]"
681   "*When numbering headings, ignore headings matching this regexp.
682 at the beginning of first word."
683   :type  'string
684   :group 'TinyTf)
685
686 (defcustom tinytf-:sentence-end "[.?!][]\"')}]*[ \r\n]+"
687   "*Like `sentence-end'. Used only in movement commands."
688   :type 'string
689   :group 'TinyTf)
690
691 (defcustom tinytf-:paragraph-start "^[ \t]*$"
692   "*Like `paragraph-start'. Used only in movement commands."
693   :type 'string
694   :group 'TinyTf)
695
696 (when (ti::emacs-p "21") ;; Variable width faces available
697
698   (defface tinytf-quote-face
699     '((((type tty pc) (class color))
700        (:foreground "lightblue" :weight bold))
701       (t (:height 1.0 :family "Georgia" )))
702     "Face for real quotes"
703     :group 'TinyTf)
704
705   (defvar tinytf-quote-face 'tinytf-quote-face)
706
707   (defface tinytf-quote2-face
708     '((((type tty pc) (class color))
709        (:foreground "lightblue" :weight bold))
710       (t (:height 1.2 :family "helv" :italic t)))
711     "Face for temporary highlight quote"
712     :group 'TinyTf)
713
714   (defvar tinytf-quote2-face 'tinytf-quote2-face)
715
716   (defface tinytf-level-1-face
717     '((((type tty pc) (class color)) (:foreground "blue" :weight bold))
718       (t (:height 1.2 :inherit tinytf-level-2-face)))
719     "Face for titles at level 1."
720     :group 'TinyTf)
721
722   (defvar tinytf-level-1-face 'tinytf-level-1-face)
723
724   (defface tinytf-level-2-face
725     '((((type tty pc) (class color)) (:foreground "lightblue" :weight bold))
726       (t (:height 1.2 :inherit tinytf-level-3-face)))
727     "Face for titles at level 2."
728     :group 'TinyTf)
729
730   (defvar tinytf-level-2-face 'tinytf-level-2-face)
731
732   (defface tinytf-level-3-face
733     '((((type tty pc) (class color)) (:foreground "black" :weight bold))
734       (t (:height 1.2 :inherit variable-pitch)))
735     "Face for titles at level 3."
736     :group 'TinyTf)
737
738   (defvar tinytf-level-3-face 'tinytf-level-3-face))
739
740 ;; Order of these rexeps is very important; because there are many
741 ;; "override" flags set to 't.
742 ;;
743 ;; 1999-11-23 `font-lock-other-type-face' doesn't exist in XEmacs 21.1.6
744 ;;
745 ;; Please COPY this variable settign to your $HOME/.emacs if you
746 ;; want to change the colors. substitute `defcustom' with `setq'
747 ;; and delete the variable comments at the end.
748
749 (defcustom tinytf-:font-lock-keywords ;; &font
750   (list
751
752    ;; Bullet
753
754    (list
755     (concat (concat "^" (make-string 8 ?\ ) "[o.]   "))
756     0 'font-lock-reference-face)
757
758    ;; bullet continue comma
759
760    (list
761     (concat (concat "^" (make-string 12 ?\ ) "[,]"))
762     0 'font-lock-reference-face)
763
764    ;;  #REF and other user defined markers. See perl script
765    ;;  for option --reference REF=value  that lets you define
766    ;;  any markers.
767
768    (list
769     (concat "^"
770             (make-string 8 ?\ )
771             "#"
772             "[^ \t\r\r\n][^ \t\r\n][^ \t\r\n]+")
773     0 'font-lock-type-face)
774
775    ;; Column 2 small bold blue
776
777    (list
778     (concat "^  \\([^ \t].*\\)$")
779     1 'font-lock-builtin-face)
780
781    ;; Column 3, emphasized
782
783    (list
784     (concat "^   \\([^ \t].*\\)$")
785     1 'font-lock-constant-face)
786
787    ;; Column 5 and 6
788
789    (list
790     (concat "^     \\([^ \t].*\\)$")
791     1
792     'font-lock-type-face)
793
794    (list
795     (concat "^      \\([^ \t].*\\)$")
796     1
797     (if (or (and (fboundp 'get-face) ;;  XEmacs
798                  (get-face 'tinytf-quote-face))
799             (facep 'tinytf-quote-face))
800         'tinytf-quote-face
801       'font-lock-comment-face))
802
803    ;; Colum 7, leading double quote
804
805    (list
806     (concat "^" (make-string 7 ?\ ) "\\(\"[^ \t].*\\)$")
807     1 'font-lock-comment-face)
808
809    ;; Colum 7 and 9, Strong [Small level 3 headers]
810
811    (list
812     (concat "^" (make-string 7 ?\ ) "\\([^ \t].*\\)$")
813     1
814     (if (or (and (fboundp 'get-face) ;;  XEmacs
815                  (get-face 'tinytf-level-3-face))
816             ;; Only works in Emacs. Returns nil in XEmacs
817             (facep 'tinytf-level-3-face))
818         'tinytf-level-3-face
819       'font-lock-comment-face)
820     t)
821
822    (list
823     (concat "^" (make-string 9 ?\ ) "\\([^ \t].*\\)$")
824     1 'font-lock-comment-face)
825
826    ;;  Colum 10, Quotation
827
828    (list
829     (concat "^" (make-string 10 ?\ ) "\\([^ \t].*\\)$")
830     1
831     (if (or (and (fboundp 'get-face) ;;  XEmacs
832                  (get-face 'tinytf-quote2-face))
833             (facep 'tinytf-quote2-face))
834         'tinytf-quote2-face
835       'font-lock-type-face))
836
837    (list
838     (concat "^" (make-string 11 ?\ ) "\\([^ \t].*\\)$")
839     1 'font-lock-constant-face)
840
841    ;; ..................................................... emphasisis ...
842
843    ;; _bold_ *italic*  and =small=
844
845    '("_[^ \t\r\n]+_"  0 font-lock-type-face)
846
847    '("\\*[^ \t\r\n]+\\*" 0 font-lock-variable-name-face)
848
849    '(" =[^ '\t\r\n]+="    0 font-lock-builtin-face prepend)
850
851    ;; ISO standard date YYYY-MM-DD HH:MM
852
853    (list
854     (concat
855      "\\<[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]")
856     0 'font-lock-keyword-face)
857
858    ;; .................................................... references ...
859
860    ;;  A long reference. There must be space somewhere otherwise
861    ;;  this regexp would overlap with the shorter reference
862    ;;  (font lock would do double job)
863    ;;
864    ;;       [1998-08 Phil carmody pc@foo.com in vegetarian-L]
865
866    (list
867     (let* ((re "\\(\\[[^][\r\n]+ [^][\r\n]+\\]\\)"))
868       (concat
869        "^"
870        ;; At column 8
871        (make-string 8 ?\ )
872        re))
873     1 'font-lock-keyword-face t)
874
875    (list
876     "\\(\\[[^][\r\n]+ [^][\r\n]+\\]\\)"
877     1 'font-lock-keyword-face)
878
879    ;;  When you refer to people or to document you do it like this
880    ;;
881    ;;       [phil] said that [perlguts] is the document you should read..
882
883    '("\\(\\[[^ \t\r\n]+\\]\\)" 1 font-lock-type-face t)
884
885    ;; ........................................................ strings ...
886
887    ;; Big letter words
888
889    '("\\<[A-Z][-/_.A-Z0-9]+\\>"  0 font-lock-variable-name-face)
890
891    ;; `this-string'
892
893    '("`\\([^ '\t\r\n]+\\)'" 1 font-lock-reference-face prepend)
894
895    ;; ........................................................... urls ...
896
897    ;; File names or programs
898
899    '("[ \t\r\n][\\/][^ \t\r\n]+\\>" 0 font-lock-comment-face t)
900
901    ;;  URL highlighting, we won't highlight Whole URL, because
902    ;;  then the document would look like Xmas tree if it had
903    ;;  hundreads of links. (or tens of links)
904
905    (list
906     (concat "\\(http\\|ftp\\|news\\|wais\\)://"
907             "\\|file:/"
908             "\\|[\\][\\][^ \t\r\n]+" ;; UNC \\machine\dir
909
910             ;;  There is no good regexp to detect Win32 idiotic
911             ;;  "space in filenames"
912
913             "\\|\\<[a-zA-Z]:[\\][^ \t\r\n]+" ;; c:\windows\file.txt
914             "\\|\\<\\([a-zA-Z]:\\)?/[^ \t\r\n]+") ;; c:/windows/file.txt
915     0 'font-lock-reference-face t)
916    ;;   <foo@site.com> Email URLs.
917    '("\\(<[^ \t\r\n]+@[^ \t\r\n]+>\\)" 1 font-lock-reference-face t)
918
919 ;;;   (list
920 ;;;    (concat "^" (make-string 12 ?\ ) "\\(.*\\)$")
921 ;;;    '(1 font-lock-reference-face))
922
923 ;;; #todo: Hmm, font-lock doesn't allow calling functions?
924
925 ;;; The font-lock could also call functions that set the matched regions.
926 ;;; However that doesn't seem to work. The code snippet below hangs,
927 ;;; But if called directly via M-x tinytf-code-p, it works ok. Don't
928 ;;; know what is the problem,
929
930 ;;;   '(tinytf-code-p . font-lock-reference-face)
931
932    ;; ........................................................ heading ...
933    ;;  Headings 1 and 2
934
935    (list
936     "^\\([.A-Z0-9].*\\)$"
937     1
938     (if (or (and (fboundp 'get-face) ;;  XEmacs
939                  (get-face 'tinytf-level-1-face))
940             ;; Only works in Emacs. Returns nil in XEmacs
941             (facep 'tinytf-level-1-face))
942         'tinytf-level-1-face
943       'font-lock-keyword-face)
944     t)
945
946    (list
947     "^    \\([.A-Z0-9].*\\)$"
948     1
949     (if (or (and (fboundp 'get-face) ;;  XEmacs
950                  (get-face 'tinytf-level-2-face))
951             ;; Only works in Emacs. Returns nil in XEmacs
952             (facep 'tinytf-level-2-face))
953         'tinytf-level-2-face
954       'font-lock-keyword-face)
955     t))
956   ;;    font-lock-reference-face    font-lock-keyword-face
957   ;;    font-lock-type-face         font-lock-function-name-face
958   ;;    font-lock-string-face       font-lock-comment-face
959   ;;    font-lock-variable-name-face
960   ;;
961   ;;    font-lock-keywords
962
963   "*Font lock keywords."
964   :type   'sexp
965   :group  'TinyTf)
966
967 ;;}}}
968 ;;{{{ suetup: private variables
969
970 (defvar tinytf-:process-compile-html "tinytf-compile-html"
971   "Name of the buffer/mode used for HTML compiling.")
972
973 (defvar tinytf-:process-compile-link "tinytf-compile-link"
974   "Name of the buffer/mode used for HTML link check.")
975
976 (defvar tinytf-:file-last-html-generated nil
977   "Filename of the last HTML generation.")
978
979 (defconst tinytf-:factor 4
980   "The indent factor. DO NOT CHANGE THIS. It is hard coded to 4.")
981
982 (defconst tinytf-:heading-number-level 2
983   "*Number of levels. Zero based. Allow values 0,1,2.")
984
985 (defvar tinytf-:counter nil
986   "Post command counter.")
987 (make-variable-buffer-local 'tinytf-:counter)
988
989 (defvar tinytf-:buffer-heading "*tinytf-headings*"
990   "List of gatehered Headings from buffer.")
991
992 (defvar tinytf-:buffer-html-process "*tinytf-t2html*"
993   "Output of t2html.pl run.")
994
995 (eval-and-compile
996   ;; Needed in defvar
997   (defsubst tinytf-indent (&optional level)
998     "Return indent space string at LEVEL. Default is 0."
999     (cond
1000      ((eq level 2)
1001       (make-string (+ (* 4 1) 3) ?\  ))
1002      (t
1003       (make-string (* tinytf-:factor (or level 0)) ?\ )))))
1004
1005 (defvar tinytf-:add-log-current-defun-header-regexp
1006   (concat
1007    ;; [text]    Detect heading Levels 1 and 2 with possible numbering
1008    ;;
1009    ;;   1.0 Heading level one
1010    ;;
1011    ;;       1.1 Heading level two
1012
1013    "^\\(    [0-9]+\\(\\.[0-9.]+\\)+[ \t]+[A-Z].*"
1014    "\\|^[0-9]+\\(\\.[0-9.]+\\)+[ \t]+[A-Z].*"
1015    "\\|^    [A-Z].*"
1016    "\\|^[A-Z].*"
1017    "\\)")
1018   "*Additional ChangeLog regepx to recognize tinytf.el headings.
1019 This variable's locally set to `add-log-current-defun-header-regexp'
1020 when `tinytf-mode' is turned on.")
1021
1022 (defvar tinytf-:heading-ignore-regexp-form
1023   '(concat
1024     "Table [Oo]f [Cc]ontents"
1025     ;;  This is special <HR> mark, see t2html.pls
1026     "\\|^[ \t]*!!"
1027     "\\|^[0-9.]*[ \t]*End[ \t]*$"
1028     "\\|End[ \t]+of[ \t]+\\(file\\|document\\)[ \t]*$"
1029     "\\|"
1030     (concat "^" ;; \\(" (tinytf-indent 0) "\\|"
1031             "\\("  (tinytf-indent 1) "\\)?"
1032             tinytf-:heading-regexp-no-numbering))
1033   "When making Table Of Contents, ignore these headings.
1034 This variable contains Lisp form that is evaled to get the string.
1035 If nil, then include all headings, dropping none.")
1036
1037 (defconst tinytf-:column-table
1038   '(
1039     ;;  First the most common positions.
1040     (0   ((nil "Heading 0")))
1041     (4   ((nil "Heading 1")))
1042     (8   ((nil "Standard text")))
1043     ;; Then special positions
1044     (1   ((nil "Emphatised")))
1045     (2   ((nil "Emphatised")))
1046     (3   ((nil "Emphatised")))
1047     (5   ((nil "Normal text, colored")))
1048     (6   ((nil "Normal text, colored")))
1049     (7   (("\"" "Emphatised")
1050           (nil  "Heading 3, Strong")))
1051     (8   (("o "
1052            "Bullet, reguler")
1053           ("\. "
1054            "Bullet, numbered")
1055           ("\.[^ \t]"
1056            "Single line, <BR> added to the end of line")
1057           (",[^ \t]"
1058            "Line continues in next chapter. <P> code not added")))
1059     (9   ((nil "Strong")))
1060     (10  ((nil "Quotation, emphatised")))
1061     (11  ((nil "Normal, colored.")))
1062
1063     (12  ((",[^ \t]"
1064            "Bullet continues in next chapter. <P> code not added")
1065           (nil
1066            "Sample"))))
1067   "Column positions and their properties. DO NOT TOUCH THIS.
1068 The positions are fixed and reflect the perl program t2html.pl's HTML generation.
1069
1070 Format:
1071  '((COL ((REGEXP-OR-NIL EXPLANATION-STRING)
1072          (REGEXP-OR-NIL EXPLANATION-STRING)
1073          ..))
1074    (COL ((RE EXPL) (RE EXPL) ..)))")
1075
1076 (defvar tinytf-:saved-indent-tabs-mode
1077   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1078
1079 (defvar tinytf-:saved-left-margin
1080   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1081
1082 (defvar tinytf-:saved-tinytab-mode
1083   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1084
1085 (defvar tinytf-:saved-font-lock-keywords
1086   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1087
1088 (defvar tinytf-:saved-auto-fill-function
1089   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1090
1091 (defvar tinytf-:saved-auto-fill-inhibit-regexp
1092   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1093
1094 (defvar tinytf-:saved-comment-start
1095   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1096
1097 (defvar tinytf-:saved-comment-end
1098   "Buffer local variable. Holds copy of original value before `tinytf-mode'.")
1099
1100 ;;}}}
1101 ;;{{{ Experimental
1102
1103 ;;; ----------------------------------------------------------------------
1104 ;;; #todo: experimental
1105 (defun tinytf-code-p (&optional limit)
1106   "Determine if current text is code. LIMIT parameter is passed by font-lock."
1107   (let* ((re  (eval-and-compile (concat "^" (make-string 12 ?\ )))))
1108     (and
1109      (save-excursion
1110        (beginning-of-line)
1111        (and (looking-at re)             ;match to return to font-lock
1112             (goto-char (match-end 0))
1113             (looking-at "\\(.*\\)$")))
1114      (save-excursion
1115        (save-match-data                 ;Now check if it was really ok
1116          (message (ti::read-current-line))
1117          (backward-line 1)
1118          (or (looking-at re)
1119              (progn
1120                ;;  skip empty lines
1121                (while (and (not (bobp))
1122                            (not (input-pending-p))
1123                            (looking-at "^[ \t]*$"))
1124                  (backward-line 1))
1125                (message (ti::read-current-line))
1126
1127                (when (and
1128                       (not (input-pending-p))
1129                       ;; Same indentation still
1130                       (looking-at re)   )
1131                  ;;  Not a P-comma code in bullet?
1132                  (not (looking-at ".*[,o.]"))))))))))
1133
1134 ;;; ----------------------------------------------------------------------
1135 ;;; #todo:
1136 ;;;
1137 (defun tinytf-tmp-swallow-empty-backwards ()
1138   (interactive)
1139   (previous-line 1)
1140   (while
1141       (and
1142        (not (bobp))
1143        (looking-at "^$"))
1144     (previous-line 1)))
1145
1146 ;;; ----------------------------------------------------------------------
1147 ;;; #todo:
1148 ;;;
1149 (defun tinytf-tmp-swallow-code-backwards ()
1150   (interactive)
1151   (let* ((re         (eval-and-compile (concat "^" (make-string 12 ?\ ))))
1152          (b-cont-re  (eval-and-compile (concat "^" (make-string 12 ?\ ) ",")))
1153          (empty      (eval-and-compile (concat "^$"))))
1154     ;;(message "gulp")
1155     (beginning-of-line)
1156     (while
1157         (and
1158          (not (bobp))
1159          (looking-at re))
1160       (previous-line 1))
1161     (if (and
1162          (not (bobp))
1163          (looking-at empty))
1164         (progn
1165           (tinytf-tmp-swallow-empty-backwards)
1166           (and
1167            (not (looking-at b-cont-re))
1168            (looking-at re)
1169            (tinytf-tmp-swallow-code-backwards))))))
1170
1171 ;;; ----------------------------------------------------------------------
1172 ;;; #todo:
1173 ;;;
1174 (defun tinytf-tmp-dxc-code-p (&optional limit)
1175   (interactive)
1176   (let* ((bullet (eval-and-compile
1177                    (concat (concat "^" (make-string 8 ?\ ) "[o.] "))))
1178          (re (eval-and-compile (concat "^" (make-string 12 ?\ ))))
1179          (b-cont-re (eval-and-compile (concat "^" (make-string 12 ?\ ) ",")))
1180          (empty (eval-and-compile (concat "^$"))))
1181
1182     (and
1183      (save-excursion
1184        (beginning-of-line)
1185        (and (looking-at re)
1186             (goto-char (match-end 0))
1187             ;; match to return to font-lock
1188             (looking-at "\\(.*\\)$"))))
1189     (save-match-data
1190       (save-excursion
1191         (beginning-of-line)
1192         (if (looking-at empty)
1193             (tinytf-tmp-swallow-empty-backwards))
1194         (if (not (looking-at re))
1195             nil
1196           (progn
1197             (tinytf-tmp-swallow-code-backwards)
1198             (not (or (looking-at b-cont-re)
1199                      (looking-at bullet)))))))))
1200
1201 ;;; ----------------------------------------------------------------------
1202 ;;; a simple one for testing only.
1203 ;;; #todo:
1204
1205 (defun tinytf-tmp-dxc-2-code-p (&optional limit)
1206   (interactive)
1207   (let* ((re (eval-and-compile (concat "^" (make-string 12 ?\ )))))
1208     (save-excursion
1209       (beginning-of-line)
1210       (looking-at re))))
1211
1212 ;;}}}
1213 ;;{{{ version
1214
1215 ;;;###autoload (autoload 'tinytf-version "tinytf" "Display commentary." t)
1216
1217 (eval-and-compile
1218   (ti::macrof-version-bug-report
1219    "tinytf.el"
1220    "tinytf"
1221    tinytf-:version-id
1222    "$Id: tinytf.el,v 2.93 2007/05/07 10:50:14 jaalto Exp $"
1223    '(tinytf-:version-id
1224      tinytf-:load-hook
1225      tinytf-:mode-define-keys-hook
1226      tinytf-:mode-hook
1227      tinytf-mode
1228      tinytf-:mode-map
1229      tinytf-:counter
1230      tinytf-:mode-name
1231      tinytf-:mode-prefix-key
1232      tinytf-:heading-regexp
1233      tinytf-:factor
1234      tinytf-:column-table)))
1235
1236 ;;}}}
1237 ;;{{{ Minor Mode definition
1238
1239 ;;; .......................................................... &v-mode ...
1240 ;;;###autoload (autoload 'tinytf-install-mode       "tinytf" "" t)
1241 ;;;###autoload (autoload 'tinytf-mode               "tinytf" "" t)
1242 ;;;###autoload (autoload 'turn-on-tinytf-mode       "tinytf" "" t)
1243 ;;;###autoload (autoload 'turn-off-tinytf-mode      "tinytf" "" t)
1244 ;;;###autoload (autoload 'tinytf-commentary         "tinytf" "" t)
1245
1246 (eval-and-compile
1247   (ti::macrof-minor-mode-wizard
1248    "tinytf-" " Tf" "\C-c\C-z" "Tf" 'TinyTf "tinytf-:" ;1-6
1249
1250    "Minor mode for writing and editing text in technical format (TF).
1251 The text layout presented in this minor mode is ment to be
1252 feed to t2html.pls perl script which generates html out of
1253 plain text file.
1254
1255 The perl code is included in source file and can be unpacked with
1256 command \\[tinytf-install-files]
1257
1258 To see the complete layout description and rules,
1259 run command `tinytf-commentary'. However, this description
1260 may be a little out of synch and you should consult perl file
1261 t2html.pl, available at nearest Perl CPAN http://cpan.perl.org/, for
1262 up to date description.
1263
1264 Mode description:
1265
1266 \\{tinytf-:mode-prefix-map}
1267 "
1268
1269    "Technical text format"
1270
1271    (progn
1272      ;;  reinstall is done every time, because some key definitions
1273      ;;  are built dynamically from current/global map
1274      ;;  Make C-x 4 a to detect text headings for ChangeLog
1275      (tinytf-install-add-log  (if tinytf-mode
1276                                   nil
1277                                 'remove))
1278      (cond
1279       (tinytf-mode
1280        (tinytf-utility-programs-check)
1281        (with-buffer-modified
1282          (tinytf-install-mode)
1283          (make-local-variable 'tinytf-:saved-indent-tabs-mode)
1284          (make-local-variable 'tinytf-:saved-left-margin)
1285          (make-local-variable 'tinytf-:saved-tinytab-mode)
1286          (make-local-variable 'tinytf-:saved-font-lock-keywords)
1287          (make-local-variable 'tinytf-:saved-comment-start)
1288          (setq tinytf-:saved-indent-tabs-mode  indent-tabs-mode)
1289          (setq tinytf-:saved-left-margin       left-margin)
1290          (setq tinytf-:saved-tinytab-mode      tinytab-mode)
1291          ;;  Emacs 21.2 newcomment.el breaks if these are not set
1292          ;;  properly. When auto-fill-mode is on, the call chain is:
1293          ;;
1294          ;;   newline
1295          ;;     self-insert-command
1296          ;;       do-auto-fill
1297          ;;         comment-indent-new-line  (newcomment.el)
1298          ;;           comment-normalize-vars
1299          (setq tinytf-:saved-comment-start     comment-start)
1300          (setq tinytf-:saved-comment-end       comment-end)
1301          (setq comment-start "")
1302          (setq comment-end "")
1303          ;;  When auto fill is used, do not indent lines that
1304          ;;  contain special tags starting with "#", which may continue
1305          ;;  past the right side. The tags must all be in one line, not
1306          ;;  broken to multiple lines:
1307          ;;
1308          ;;      #PIC pic/this-picture.jpg # Explanation which is long .....  ###
1309          ;;
1310          ;;  Also, do not break long headings.
1311          ;;
1312          ;;      2.2 This long chapter ....
1313          (make-local-variable 'auto-fill-inhibit-regexp)
1314          (setq tinytf-:saved-auto-fill-inhibit-regexp auto-fill-inhibit-regexp)
1315          (setq auto-fill-inhibit-regexp "^[ \t]+#\\|^[ \t]+[0-9]\\.[0-9] [A-Z]")
1316          (make-local-variable 'tinytf-:saved-auto-fill-function)
1317          (setq tinytf-:saved-auto-fill-function auto-fill-function)
1318          (turn-on-auto-fill-mode)
1319          (setq selective-display            t
1320                selective-display-ellipses   t
1321                ;; left-margin               8  ;; for return key
1322                indent-tabs-mode             nil)
1323          (unless tinytab-mode ;;Turn on this mode
1324            (setq tinytf-:saved-tinytab-mode nil)
1325            (turn-on-tinytab-mode))
1326          (setq tinytab-:div-factor 4) ;; advance by four spaces
1327          ;;  Make sure RETURN key continues indent.
1328          (turn-on-tinytab-return-key-mode)
1329          ;;  Single space ends sentence. The Emacs default is some
1330          ;;  old relict that nobody uses, or should use any more.
1331          (make-local-variable 'sentence-end-double-space)
1332          (setq sentence-end-double-space nil)
1333          ;; (make-local-variable 'sentence-end)
1334          ;; (setq sentence-end "[.?!][]\"')}]*\\($\\|[ \t]\\)[ \t\r\n]*"
1335          ;;  Use our font lock keywords this time and save original
1336          (when (boundp 'font-lock-keywords)
1337            (setq tinytf-:saved-font-lock-keywords font-lock-keywords)
1338            (tinytf-font-lock-mode))))
1339       (t
1340        (with-buffer-modified
1341          ;; Restore values
1342          (setq indent-tabs-mode         tinytf-:saved-indent-tabs-mode)
1343          (setq auto-fill-function       tinytf-:saved-auto-fill-function)
1344          (setq auto-fill-inhibit-regexp tinytf-:saved-auto-fill-inhibit-regexp)
1345          (setq comment-start            tinytf-:saved-comment-start)
1346          (when (integerp tinytf-:saved-left-margin)
1347            (setq left-margin tinytf-:saved-left-margin))
1348          (if tinytf-:saved-tinytab-mode
1349              (turn-on-tinytab-mode)
1350            (turn-off-tinytab-mode))
1351          (setq selective-display nil)
1352          (tinytf-show-buffer)
1353          (when (boundp 'font-lock-keywords)
1354            (setq font-lock-keywords tinytf-:saved-font-lock-keywords)
1355            (when (ti::colors-supported-p)
1356              (save-excursion
1357                ;;  force font lock to rework everything
1358                (set-buffer-modified-p nil)
1359                (set-text-properties (point-min) (point-max) nil)
1360                (tinytf-fontify-current-buffer-window))))))))
1361
1362    "Technical text writing menu."
1363
1364    (list
1365     tinytf-:mode-easymenu-name
1366     "Markup"
1367     ["Mark word strong"       tinytf-mark-word-strong       t]
1368     ["Mark word sample"       tinytf-mark-word-sample       t]
1369     ["Mark word emphatised"   tinytf-mark-word-emp          t]
1370     ["Mark word small"        tinytf-mark-word-small        t]
1371     ["Mark word big"          tinytf-mark-word-big          t]
1372     ["Mark <BR> line"         tinytf-mark-br-line           t]
1373     ["Mark <BR> paragraph"    tinytf-mark-br-paragraph      t]
1374     ["Unmark word"            tinytf-unmark-word            t]
1375     "Indentation"
1376     ["Convert to bullet"      tinytf-bullet-format          t]
1377     ["Indent paragraph text"  tinytf-indent-paragraph-text  t]
1378     ["Indent paragraph text 'as is'"  tinytf-indent-paragraph-text-as-is  t]
1379     ["Indent paragraph text and fill"  tinytf-indent-paragraph-text-and-fill  t]
1380     ["Indent paragraph Quote"   tinytf-indent-paragraph-quote  t]
1381     ["Indent paragraph Quote and fill" tinytf-indent-paragraph-quote-and-fill t]
1382     ["Indent paragraph Sample"  tinytf-indent-paragraph-sample t]
1383     (list
1384      "Indent by column"
1385      ["Indent paragraph zero"  tinytf-indent-paragraph-zero t]
1386      ["Indent paragraph 2"     tinytf-indent-paragraph-2    t]
1387      ["Indent paragraph 3"     tinytf-indent-paragraph-3    t]
1388      ["Indent paragraph 5"     tinytf-indent-paragraph-5    t]
1389      ["Indent paragraph 6"     tinytf-indent-paragraph-6    t]
1390      ["Indent paragraph 11"    tinytf-indent-paragraph-11   t])
1391     "----"
1392     (list
1393      "HTML"
1394      "t2html"
1395      ["HTML basic" tinytf-convert-t2html-basic
1396       (get 'tinytf-mode  't2html)]
1397      ["HTML frames" tinytf-convert-t2html-frame
1398       (get 'tinytf-mode  't2html)]
1399      ["HTML as you see" tinytf-convert-t2html-as-is
1400       (get 'tinytf-mode  't2html)]
1401      ["Link check" tinytf-convert-t2html-link-check
1402       (get 'tinytf-mode  't2html)]
1403      ["Link check (with cache)" tinytf-convert-t2html-link-check-cached
1404       (get 'tinytf-mode  't2html)]
1405      "----"
1406      "htmlize"
1407      ["HTML buffer"  tinytf-convert-htmlize
1408       (get 'tinytf-mode  'htmlize)]
1409      "----"
1410      ["View HTML with browser"  tinytf-convert-view-default t]
1411      ["View HTML source"        tinytf-convert-view-html-source t]
1412      "----"
1413      ["Conversion preferences"  tinytf-convert-preference-set t]
1414      ["Conversion menu re-evaluate" tinytf-utility-programs-check-force t])
1415     (list
1416      "Indent Region"
1417      ["Indent region strong"   tinytf-indent-region-strong   t]
1418      ["Indent region sample"   tinytf-indent-region-sample   t]
1419      ["Indent region quote"    tinytf-indent-region-quote    t]
1420      ["Indent region text"     tinytf-indent-region-text     t])
1421     (list
1422      "Headings"
1423      "Heading management"
1424      ["Heading 1 backward"     tinytf-heading-backward-0     t]
1425      ["Heading 1 forward"      tinytf-heading-forward-0      t]
1426      ["Heading 2 backward"     tinytf-heading-backward-any   t]
1427      ["Heading 2 forward"      tinytf-heading-forward-any    t]
1428      "----"
1429      ["Heading numbering"      tinytf-heading-numbering      t]
1430      ["Heading fix 1st chars"  tinytf-heading-fix            t]
1431      ["Heading fix case"       tinytf-heading-fix-case       t]
1432      ["Heading fix case all"   tinytf-heading-fix-case-all   t]
1433      "----"
1434      ["Paragraph forward"      tinytf-forward-paragraph      t]
1435      ["Paragraph backward"     tinytf-backward-paragraph     t])
1436     (list
1437      "Outline"
1438      ["Hide buffer"            tinytf-hide-buffer            t]
1439      ["Show buffer"            tinytf-show-buffer            t]
1440      ["Hide heading"           tinytf-hide                   t]
1441      ["Show heading"           tinytf-show                   t]
1442      ["Show/hide toggle"       tinytf-show-toggle            t])
1443     (list
1444      "Misc"
1445      ["Toc create"             tinytf-toc                     t]
1446      ["Toc popup"              tinytf-toc-mouse               t]
1447      ["Toc Occur"              tinytf-toc-occur               t]
1448      "----"
1449      ["Selective display copy"  ti::buffer-selective-display-copy-to t]
1450      ["Selective display print" ti::buffer-selective-display-print   t]
1451      "----"
1452      ["Untabify buffer"        tinytf-untabify-buffer         t]
1453      ["Column info"            tinytf-column-info-display     t])
1454     "----"
1455     "Package functions"
1456     ["Package version"        tinytf-version                  t]
1457     ["Package commentary"     tinytf-commentary               t]
1458     ["Mode and menu reload"   tinytf-mode-reload              t]
1459     ["Mode help"              tinytf-mode-help                t]
1460     ["Mode exit and cleanup"  tinytf-exit                     t]
1461     ["Mode exit"              turn-off-tinytf-mode            t])
1462    (progn
1463      (let* ()
1464        (define-key map  "?"  'tinytf-mode-help)
1465        (define-key map  "H"   nil)
1466        (define-key map  "Hm" 'tinytf-mode-help)
1467        (define-key map  "Hc" 'tinytf-commentary)
1468        (define-key map  "Hv" 'tinytf-version)
1469        (define-key map  "n"  'tinytf-heading-numbering)
1470        (define-key map  "u"  'tinytf-untabify-buffer)
1471        ;;  Toc
1472        ;;  mouse binding "Prefix + mouse-1"
1473        (define-key map  "T" 'tinytf-toc)
1474        (define-key map  "O" 'tinytf-toc-occur)
1475        (if (ti::emacs-p)
1476            (define-key map [(mouse-1)] 'tinytf-toc-mouse)
1477          (define-key map [(button1)] 'tinytf-toc-mouse))
1478        ;;
1479        ;;  Marking commands in non-shift keys
1480        ;;  STRONG = "."; like a heavy statement that
1481        ;;  ends like this: "I said that. Perioti::d!"
1482        ;;
1483        ;;  It is most likely that you "EMP" characters most of the time;
1484        ;;  That's why "`" is not defined as "w-". And to Undo easily
1485        ;;  marking, the unmark must be fast to access via " ".
1486        ;;
1487        (define-key map  " "  'tinytf-unmark-word)
1488        (define-key map  "-" 'tinytf-mark-word-strong)
1489        (define-key map  "'" 'tinytf-mark-word-sample) ;; code
1490        (define-key map  "*" 'tinytf-mark-word-emp)    ;; italics
1491        (define-key map  "+" 'tinytf-mark-word-big)
1492        (define-key map  "_" 'tinytf-mark-word-small)
1493        (define-key map  "mB" 'tinytf-mark-br-line)
1494        (define-key map  "mb" 'tinytf-mark-br-paragraph)
1495        ;;  If you're converting some document to TF format,
1496        ;;  therse are the commands you will use 80% of the time.
1497        (define-key map  "rS" 'tinytf-indent-region-strong)
1498        (define-key map  "rs" 'tinytf-indent-region-sample)
1499        (define-key map  "rq" 'tinytf-indent-region-quote)
1500        (define-key map  "rt" 'tinytf-indent-region-text)
1501        (define-key map  "c"   nil)
1502        (define-key map  "ct"  nil)
1503        (define-key map  "chb" 'tinytf-convert-t2html-basic)
1504        (define-key map  "chf" 'tinytf-convert-t2html-frame)
1505        (define-key map  "cha" 'tinytf-convert-t2html-as-is)
1506        (define-key map  "chl" 'tinytf-convert-t2html-link-check)
1507        (define-key map  "chL" 'tinytf-convert-t2html-link-check-cached)
1508        (define-key map  "chH" 'tinytf-convert-htmlize)
1509        (define-key map  "cr"  'tinytf-utility-programs-check-force)
1510        (define-key map  "cp"  'tinytf-convert-preference-set)
1511        (define-key map  "cvv" 'tinytf-convert-view-default)
1512        (define-key map  "cvf" 'tinytf-convert-view-html-source)
1513        (define-key map  "b" 'tinytf-bullet-format)
1514        (define-key map  "t" 'tinytf-indent-paragraph-text)
1515        (define-key map  "a" 'tinytf-indent-paragraph-text-as-is)
1516        ;; l = fil(l)
1517        (define-key map  "l" 'tinytf-indent-paragraph-text-and-fill)
1518        (define-key map  "q" 'tinytf-indent-paragraph-quote-and-fill)
1519        (define-key map  "Q" 'tinytf-indent-paragraph-quote)
1520        (define-key map  "s" 'tinytf-indent-paragraph-sample)
1521        (define-key map  "0" 'tinytf-indent-paragraph-zero)
1522        (define-key map  "1" 'tinytf-indent-paragraph-11)
1523        (define-key map  "2" 'tinytf-indent-paragraph-2)
1524        (define-key map  "3" 'tinytf-indent-paragraph-3)
1525        (define-key map  "5" 'tinytf-indent-paragraph-5)
1526        (define-key map  "6" 'tinytf-indent-paragraph-6)
1527        (define-key map  "f"  nil)
1528        (define-key map  "fa" 'tinytf-fix-all)
1529        (define-key map  "fh" 'tinytf-heading-fix)
1530        (define-key map  "fC" 'tinytf-heading-fix-case-all)
1531        (define-key map  "fc" 'tinytf-heading-fix-case)
1532        (define-key map  "fn" 'tinytf-heading-fix-newlines)
1533        ;;  Selective display
1534        (define-key map  "Sp" 'ti::buffer-selective-display-print)
1535        (define-key map  "Sc" 'ti::buffer-selective-display-copy-to)
1536        ;;  Hiding
1537        (define-key map  "\C-q" 'tinytf-show-toggle)
1538        (define-key map  "\C-x" 'tinytf-hide)
1539        (define-key map  "\C-s" 'tinytf-show)
1540        (define-key map  "\C-w" 'tinytf-hide-buffer)
1541        (define-key map  "\C-y" 'tinytf-show-buffer)
1542        ;; Info
1543        (define-key map  "\C-m" 'tinytf-column-info-display)
1544        (define-key map  "xr"   'tinytf-mode-reload)
1545        (define-key map  "xX"   'tinytf-exit)
1546        (define-key map  "xx"   'turn-off-tinytf-mode)
1547        ;;  Original PgUp and down keys --> move under Control key
1548        (ti::copy-key-definition root-map [(control prior)]  [(prior)])
1549        (ti::copy-key-definition root-map [(control next)]   [(next)])
1550        (define-key root-map [(prior)]         'tinytf-heading-backward-any)
1551        (define-key root-map [(next)]          'tinytf-heading-forward-any)
1552        (define-key root-map [(shift prior)]   'tinytf-heading-backward-0)
1553        (define-key root-map [(shift next)]    'tinytf-heading-forward-0)
1554        ;;  The Shift-prior do not always show in non-window system, so define
1555        ;;  these:
1556        (define-key map  "\C-p" 'tinytf-heading-backward-0)
1557        (define-key map  "\C-n" 'tinytf-heading-forward-0)
1558        ;;  The 'home' and 'end' keys
1559        (ti::copy-key-definition root-map [(control end)]      [(end)])
1560        (ti::copy-key-definition root-map [(control home)]     [(home)])
1561        (ti::copy-key-definition root-map [(control select)]   [(select)])
1562        (define-key root-map [(home)]          'tinytf-backward-paragraph)
1563        (define-key root-map [(select)]        'tinytf-forward-paragraph)
1564        (define-key root-map [(end)]           'tinytf-forward-paragraph)
1565        (if (ti::emacs-p)
1566            (define-key map [(mouse-3)]
1567              'tinytf-mouse-context-sensitive)
1568          (define-key map [(button3)]
1569            'tinytf-mouse-context-sensitive))))))
1570
1571 ;;; ----------------------------------------------------------------------
1572 ;;;
1573 ;;;###autoload
1574 (defun tinytf-mode-define-f-keys ()
1575   "Define default function key to `tinytf-:mode-map'."
1576   (interactive)
1577   (let* ((map tinytf-:mode-map))
1578     ;;  more faster keys than the "w" word markup map.
1579     (define-key map [(f5)]  'tinytf-mark-word-emp)
1580     (define-key map [(f7)]  'tinytf-mark-word-strong)
1581     (define-key map [(f8)]  'tinytf-mark-word-sample)
1582     (define-key map [(f9)]  'tinytf-unmark-word)
1583     (define-key map [(f10)] 'tinytf-indent-paragraph-text-and-fill)
1584     (define-key map [(f11)] 'tinytf-indent-paragraph-quote-and-fill)
1585     (define-key map [(f12)] 'tinytf-indent-paragraph-sample)))
1586
1587 ;;; ----------------------------------------------------------------------
1588 ;;;
1589 (defun tinytf-mode-reload ()
1590   "Reload and activate greyed menus (if new programs available).
1591 If you have changed `exec-path' or added htmlize.el along
1592 `load-path' the menus do not know when this has happened.
1593
1594 Calling this function re-eaxamines available utilities."
1595   (interactive)
1596   (tinytf-utility-programs-check-force))
1597
1598 ;;}}}
1599 ;;{{{ mode install
1600
1601 ;;; ----------------------------------------------------------------------
1602 ;;;
1603 ;;;###autoload (autoload 'tinytf-install-files "tinytf" "" t)
1604 (ti::macrof-install-pgp-tar tinytf-install-files  "tinytf.el")
1605
1606 ;;; ----------------------------------------------------------------------
1607 ;;;
1608 (defun tinytf-font-lock-mode ()
1609   "Install `font-lock' support. Activates only if `tinytf-mode' is on."
1610   (when (and tinytf-mode
1611              (boundp 'font-lock-keywords)
1612              (or (and (boundp 'font-lock-mode)
1613                       font-lock-mode)
1614                  (and (boundp 'global-font-lock-mode)
1615                       global-font-lock-mode)))
1616     (when (font-lock-mode-maybe 1)
1617       (setq font-lock-keywords tinytf-:font-lock-keywords)
1618       ;;  if lazy-lock is in effect, it may not fontify the current window
1619       ;;  Do it now.
1620       (tinytf-fontify-current-buffer-window))))
1621
1622 ;;; ----------------------------------------------------------------------
1623 ;;;
1624 (defun tinytf-install-eval-after-load (&optional uninstall)
1625   "Intall or UNINSTALL `eval-after-load' for add-log.el."
1626   (let* ((form '(tinytf-install-add-log-all-buffers)))
1627     (cond
1628      (uninstall
1629       (dolist (elt after-load-alist)
1630         (when (and (string-match "add-log" (car elt))
1631                    (member form (cdr elt)))
1632           (setq after-load-alist (delete elt after-load-alist)))))
1633      (t
1634       (eval-after-load "add-log" form)))))
1635
1636 ;;; ----------------------------------------------------------------------
1637 ;;;
1638 (defun tinytf-install-add-log (&optional uninstall)
1639   "Install or UNINSTALL add-log.el support.
1640 Calling this function makes variable
1641 `add-log-current-defun-header-regexp' local in the current
1642 buffer. The variable includes regexp to match heading levels so that
1643 the ChangeLog entry is put in parentheses:
1644
1645   * file.txt (This Heading): <explanation>
1646              ==============
1647
1648 References:
1649
1650   `tinytf-:add-log-current-defun-header-regexp'."
1651   (let ((sym 'add-log-current-defun-header-regexp))
1652     (when (boundp sym)
1653       ;;  See `add-log-current-defun'
1654       (if uninstall
1655           (kill-local-variable sym)
1656         (make-local-variable sym)
1657         (set sym tinytf-:add-log-current-defun-header-regexp)))))
1658
1659 ;;; ----------------------------------------------------------------------
1660 ;;;
1661 (defun tinytf-install-add-log-all-buffers ()
1662   "Install add-log.el support for all `tinytf-mode' buffers."
1663   (ti::dolist-buffer-list
1664    (and tinytf-mode)
1665    nil
1666    nil
1667    (tinytf-install-add-log)))
1668
1669 ;;; ----------------------------------------------------------------------
1670 ;;;
1671 (defun tinytf-install (&optional uninstall verb)
1672   "Install hook to mode or UNINSTALL. VERB allows verbose messages."
1673   (interactive "P")
1674   (ti::verb)
1675   (tinytf-install-eval-after-load uninstall))
1676
1677 ;;; ----------------------------------------------------------------------
1678 ;;;
1679 (defun tinytf-text-format-not-p ()
1680   "This is backup to verify after running `tinytf-text-format-p'.
1681 Function `tinytf-text-format-p' may consider the file as TF format,
1682 but it would be good to check few things before making decisive
1683 conclusion."
1684   (let ()
1685     (or (ti::re-search-check
1686          ;;  Two consequent lines together, not good.
1687          "^[^ \t\r\n].*\\(\r\n\\|\r\\|\n\\)[^ \t\r\n]"
1688          nil nil 'read))))
1689
1690 ;;; ----------------------------------------------------------------------
1691 ;;;
1692 (defun tinytf-text-format-ok-p-test-toc ()
1693   "Check if buffer content looks like technical format.
1694 This is low level check. Use `tinytf-text-format-ok-p' instead."
1695   (ti::re-search-check
1696    ;;  1) If we see this
1697    "^Table [Oo]f [Cc]ontents[ \t]*$"
1698    nil nil 'read))
1699
1700 ;;; ----------------------------------------------------------------------
1701 ;;;
1702 (defun tinytf-text-format-ok-p-test-headings ()
1703   "Check if buffer content looks like technical format.
1704 This is low level check. Use `tinytf-text-format-ok-p' instead."
1705   ;;  See if you can find two consequtive headings. The
1706   ;;  extra ".*" at the end of regexp is just for debugging
1707   ;;  purpose: what are the lines that were matched. Headings
1708   ;;  may be numbered.
1709   ;;
1710   ;;  Heading one            1.0 Heading one
1711   ;;
1712   ;;      Heading two           1.1 Heading two
1713   (ti::re-search-check
1714    (concat
1715     "^\\(\\([0-9]\\.[0-9.]*[0-9]\\) \\)?[A-Z][^ \t\f\r\n].*"
1716     "\\(\n\n\\|\r\n\r\n\\)" ;;  Two newlines
1717     "    \\(\\([0-9]\\.[0-9.]*[0-9]\\) \\)?[A-Z][^ \t\f\r\n].*")
1718    nil nil 'read))
1719
1720 ;;; ----------------------------------------------------------------------
1721 ;;;
1722 (defun tinytf-text-format-ok-p-test-heading-and-text ()
1723   "Check if buffer content looks like technical format.
1724 This is low level check. Use `tinytf-text-format-ok-p' instead."
1725   ;;  Try to find one heading and regular text
1726   ;;
1727   ;;         Heading one
1728   ;;
1729   ;;                 And normal text at column 8
1730   ;;
1731   ;;  But take into account a special case, where the text starts
1732   ;;  at column 7, which causes it to be rendered as "small
1733   ;;  heading level 3"
1734   ;;
1735   ;;         Heading one
1736   ;;
1737   ;;                This is small heading, at column 7, offset -1
1738   ;;
1739   ;;                 And normal text at column 8
1740   ;;                 And normal text at column 8
1741   ;;
1742   ;;                This is small heading, at column 7, offset -1
1743   (ti::re-search-check
1744    (concat
1745     "^\\(    \\)?\\([0-9]\\.[0-9.]*[0-9] \\)?[A-Z][A-Za-z].*"
1746     "\\(\n\n\\|\r\n\r\n\\)"
1747     "        ? ? ?[A-Z][A-Za-z].*")
1748    nil nil 'read))
1749
1750 ;;; ----------------------------------------------------------------------
1751 ;;;
1752 (defun tinytf-text-format-ok-p ()
1753   "Check if buffer content looks like technical format."
1754   (interactive)
1755   (let* (case-fold-search
1756          ret)
1757     ;; Exclude mail messages from any checks.
1758     (unless (ti::mail-mail-p)
1759       (setq ret
1760             (or (tinytf-text-format-ok-p-test-toc)
1761                 (tinytf-text-format-ok-p-test-headings)
1762                 (tinytf-text-format-ok-p-test-heading-and-text))))
1763     (if (interactive-p)
1764         (if (null ret)
1765             (message "Tinytf: No TF formattting found in this buffer.")
1766           (message "Tinytf: Found TF format location [%s]" ret)))
1767     ret))
1768
1769 ;;; ----------------------------------------------------------------------
1770 ;;;
1771 (defun tinytf-text-format-p ()
1772   "Check if buffer looks like TF format."
1773   (and (tinytf-text-format-ok-p)
1774        (not (tinytf-text-format-not-p))))
1775
1776 ;;; ----------------------------------------------------------------------
1777 ;;;
1778 (defun tinytf-text-format-file-p ()
1779   "Test that file extension is .txt and `tinytf-text-format-p' returns t."
1780   (and (string-match
1781         "\\.txt"
1782         (or (buffer-file-name) ""))
1783        (tinytf-text-format-p)))
1784
1785 ;;; ----------------------------------------------------------------------
1786 ;;;
1787 ;;;###autoload
1788 (defun turn-on-tinytf-mode-maybe ()
1789   "If buffer looks like technical format, turn on `tinytf-mode'.
1790 References:
1791   `tinytf-:tinytf-mode-p-function'."
1792   (when (and tinytf-:tinytf-mode-p-function
1793              (funcall tinytf-:tinytf-mode-p-function))
1794     (turn-on-tinytf-mode)
1795     ;;  Hook must return nil
1796     nil))
1797
1798 ;;; ----------------------------------------------------------------------
1799 ;;;
1800 (defun turn-on-tinytf-mode-all-buffers ()
1801   "Call`tinytf-mode' on in all technical format buffers. Optionally OFF.
1802 The buffer is detected by using function strored in variable
1803 `tinytf-:tinytf-mode-p-function'"
1804   (interactive)
1805   (when tinytf-:tinytf-mode-p-function
1806     (ti::dolist-buffer-list
1807      (and (null tinytf-mode)
1808           (string-match "text" (downcase (symbol-name major-mode)))
1809           (funcall tinytf-:tinytf-mode-p-function))
1810      nil
1811      nil
1812      (turn-on-tinytf-mode))))
1813
1814 ;;}}}
1815 ;;{{{ macros, defsubst
1816
1817 ;;; These macros create functions
1818 ;;;
1819 ;;; For some unknown reason the ByteCompiler doesn't see thse
1820 ;;; function in the followed macros unless the functions are wrapped
1821 ;;; inside eval-and-compile FORM.
1822 ;;;
1823 ;;; fmacro = function create macro
1824
1825 (eval-and-compile
1826
1827 ;;; ----------------------------------------------------------------------
1828 ;;;
1829   (defun tinytf-fmacro-indent-region-1 (func doc col msg &rest body)
1830     "Use `tinytf-fmacro-indent-region' with FUNC DOC COL MSG BODY."
1831     (let* ((sym (intern (symbol-name (` (, func))))))
1832       (`
1833        (defun (, sym)  (beg end &optional verb)
1834          (, doc)
1835          (interactive "*r")
1836          (ti::verb)
1837          (let* ((reg
1838                  (tinytf-move-paragraph-to-column
1839                   beg end (, col)
1840                   (if verb
1841                       (, msg)))))
1842            (,@ body))))))
1843
1844 ;;; ----------------------------------------------------------------------
1845 ;;;
1846   (defun tinytf-fmacro-mark-word-1 (func doc char1 &optional char2)
1847     "Use `tinytf-fmacro-mark-word' with FUNC DOC CHAR1 CHAR2."
1848     (let* ((sym (intern (symbol-name (` (, func))))))
1849       (`
1850        (defun (, sym) ()
1851          (, doc)
1852          (interactive "*")
1853          (unless (ti::space-p (preceding-char))
1854            (skip-chars-backward "^ ,\t\f\r\n"))
1855          (insert (char-to-string (, char1)))
1856          (skip-chars-forward "^ ,\t\f\r\n")
1857          (insert (char-to-string (or (, char2) (, char1))))
1858          (skip-chars-forward " ,\t\f\r\n")))))
1859
1860 ;;; ----------------------------------------------------------------------
1861 ;;;
1862   (defun tinytf-paragraph-bounds ()
1863     "Return (beg . end) points of paragraph."
1864     (let* ((empty-line (ti::nil-p (ti::read-current-line)))
1865            beg
1866            end)
1867       (save-excursion
1868         (save-excursion
1869           (if (not empty-line)
1870               (or (re-search-backward "^[ \t]*$" nil t)
1871                   (ti::pmin)))
1872           (setq beg (point)))
1873         (if empty-line
1874             (skip-chars-forward " \t\r\n"))
1875         (or (re-search-forward "^[ \t]*$" nil t) (ti::pmax))
1876         (setq end (point)))
1877       (if (and beg end)
1878           (cons beg end))))
1879
1880 ;;; ----------------------------------------------------------------------
1881 ;;;
1882   (defun tinytf-fmacro-indent-paragraph-1 (func doc col msg &rest body)
1883     "Use `tinytf-fmacro-indent-paragraph'."
1884     (let* ((sym (intern (symbol-name (` (, func))))))
1885       (`
1886        (defun (, sym)  (&optional verb)
1887          (, doc)
1888          (interactive "*")
1889          (let* ((region (tinytf-paragraph-bounds))
1890                 (beg    (car-safe region))
1891                 (end    (cdr-safe region)))
1892            (ti::verb)
1893            (if (null region)
1894                (if verb (message "%s: Cannot find paragraph bounds."
1895                                  tinytf-:mode-name))
1896              (tinytf-move-paragraph-to-column
1897               beg
1898               end
1899               (, col)
1900               (if verb
1901                   (, msg))
1902               'noask)
1903              (,@ body)))))))
1904
1905 ;;; --++-- --++-- --++-- --++-- --++-- --++-- --++-- --++-- - eval end --
1906   ) ;; eval-end
1907
1908 ;;; ----------------------------------------------------------------------
1909 ;;;
1910 (defmacro tinytf-fmacro-indent-region (func doc col msg &optional body)
1911   "Create indent function FUNC with DOC COL MSG BODY.
1912 Created function arguments: (beg end &optional verb)"
1913   (` (, (tinytf-fmacro-indent-region-1
1914          func
1915          doc
1916          col
1917          msg
1918          body))))
1919
1920 ;;; ----------------------------------------------------------------------
1921 ;;;
1922 (defmacro tinytf-fmacro-mark-word (func doc char1 &optional char2)
1923   "Create word marking function FUNC with DOC and CHAR.
1924 Created function arguments: ()"
1925   (` (, (tinytf-fmacro-mark-word-1
1926          func doc char1 char2))))
1927
1928 ;;; ----------------------------------------------------------------------
1929 ;;;
1930 (put 'tinytf-fmacro-indent-paragraph 'edebug-form-spec '(body))
1931 (defmacro tinytf-fmacro-indent-paragraph (func doc col msg &optional body)
1932   "Create word marking function FUNC with DOC and COL, MSG and BODY.
1933 Created function arguments: ()"
1934   (` (, (tinytf-fmacro-indent-paragraph-1
1935          func doc col msg body))))
1936
1937 ;;; These are conventional macros
1938
1939 ;;; ----------------------------------------------------------------------
1940 ;;;
1941 (put 'tinytf-paragraph-macro 'lisp-indent-function 0)
1942 (put 'tinytf-paragraph-macro 'edebug-form-spec '(body))
1943 (defmacro tinytf-paragraph-macro (&rest body)
1944   "Set paragraph values locally while executing BODY."
1945   (`
1946    (let* ((sentence-end         tinytf-:sentence-end)
1947           (paragraph-start      tinytf-:paragraph-start)
1948           (paragraph-separate   paragraph-start))
1949      (,@ body))))
1950
1951 ;;; ----------------------------------------------------------------------
1952 ;;;
1953 (put 'tinytf-heading-macro  'lisp-indent-function 0)
1954 (put 'tinytf-heading-macro 'edebug-form-spec '(body))
1955 (defmacro tinytf-heading-macro (&rest body)
1956   "Map over every heading. The point sits at the beginning of heading text.
1957 The BODY must move the point so that next heading can be found."
1958   (`
1959    (let* ((RE-search  (concat
1960                        (tinytf-regexp)
1961                        (if (> tinytf-:heading-number-level 0)
1962                            (concat "\\|" (tinytf-regexp 1)))
1963                        (if (> tinytf-:heading-number-level 1)
1964                            (concat "\\|" (tinytf-regexp 2)))))
1965           (RE-no      (or (eval tinytf-:heading-ignore-regexp-form)
1966                           "NothingMatchesLikeThis")))
1967      (save-excursion
1968        (tinytf-heading-start)
1969        (while (re-search-forward RE-search nil t)
1970          (unless (string-match RE-no (ti::read-current-line))
1971            (,@ body)))))))
1972
1973 ;;; ----------------------------------------------------------------------
1974 ;;;
1975 (put 'tinytf-level-macro 'lisp-indent-function 0)
1976 (put 'tinytf-level-macro 'edebug-form-spec '(body))
1977 (defmacro tinytf-level-macro (&rest body)
1978   "Search begin point of current heading level or signal error.
1979 You can refer to variable 'level' and 'beg' and 'end' in the BODY.
1980 The point is at start of level."
1981   (`
1982    (let* ((level  (tinytf-level-number))
1983           beg
1984           end)
1985      (unless level
1986        (if (tinytf-heading-backward-any)
1987            (setq level (tinytf-level-number))
1988          (error "Can't find begin point")))
1989      (setq beg (point)
1990            end (tinytf-block-end))
1991      (goto-char beg)
1992      (,@ body))))
1993
1994 ;;; ----------------------------------------------------------------------
1995 ;;;
1996 (defsubst tinytf-regexp (&optional level)
1997   "Return indent regexp string at LEVEL."
1998   ;;  control character are not counted, like ^L page mark
1999   (concat "^" (tinytf-indent level) tinytf-:heading-regexp))
2000
2001 ;;; ----------------------------------------------------------------------
2002 ;;;
2003 (defsubst tinytf-level-p (&optional level)
2004   "Check if line is LEVEL."
2005   (let* (case-fold-search)              ;case sensitive match
2006     (save-excursion
2007       (beginning-of-line)
2008       (looking-at (tinytf-regexp level)))))
2009
2010 ;;; ----------------------------------------------------------------------
2011 ;;;
2012 (defsubst tinytf-level-number ()
2013   "Check current level on this line."
2014   (cond
2015    ((tinytf-level-p 0) 0)
2016    ((tinytf-level-p 1) 1)
2017    ((tinytf-level-p 2) 2)))
2018
2019 ;;; ----------------------------------------------------------------------
2020 ;;;
2021 (defsubst tinytf-block-end ()
2022   "Return text block end."
2023   (save-excursion
2024     (if (null (tinytf-heading-forward-any))
2025         (point-max)
2026       (beginning-of-line)
2027       (1- (point)))))
2028
2029 ;;; ----------------------------------------------------------------------
2030 ;;;
2031 (defsubst tinytf-heading-number-regexp (&optional no-grouping)
2032   "Return heading number regexp: match 'N.n '  or  'N.n) '.
2033 If NO-GROUPING is non-nil, the regexp will not have regexp group operator."
2034   (if no-grouping
2035       "[0-9]+\\.[0-9.]*[0-9])?[ \t]+"
2036     "\\([0-9]+\\.[0-9.]*[0-9])?[ \t]+\\)"))
2037
2038 ;;; ----------------------------------------------------------------------
2039 ;;;
2040 (defsubst tinytf-headings-numbered-p ()
2041   "Check if first heading is numbered."
2042   (save-excursion
2043     (ti::pmin)
2044     (re-search-forward (tinytf-heading-number-regexp) nil t)))
2045
2046 ;;; ----------------------------------------------------------------------
2047 ;;;
2048 (defsubst tinytf-heading-string (&rest levels)
2049   "Return heading string. 'MAJOR.MINOR '."
2050   (let ((str (number-to-string (pop levels))))
2051     (dolist (nbr levels)
2052       (setq str (concat str "." (number-to-string nbr))))
2053     (concat str " ")))
2054
2055 ;;; ----------------------------------------------------------------------
2056 ;;;
2057 (defun tinytf-goto-non-space ()
2058   "Goto first non-whitespace of bol."
2059   (beginning-of-line)
2060   (if (re-search-forward "^[ \t]+" (line-end-position) t)
2061       (goto-char (match-end 0))))
2062
2063 ;;; ----------------------------------------------------------------------
2064 ;;;
2065 (defsubst tinytf-heading-same-p (level heading-regexp)
2066   "Check if heading LEVEL is identical to HEADING-REGEXP.
2067 After the regexp there must be non whitespace, which starts the heading
2068 name."
2069   (save-match-data
2070     (save-excursion
2071       (beginning-of-line)
2072       (looking-at (concat
2073                    "^"
2074                    (tinytf-indent level)
2075                    heading-regexp
2076                    ;;  After the spaces there must be NON-space to start
2077                    ;;  the heading name
2078                    "[^ \t]")))))
2079
2080 ;;; ----------------------------------------------------------------------
2081 ;;;
2082 (defun tinytf-toc-goto ()
2083   "Goto Table of contents and return t or to `point-min'."
2084   (ti::pmin)
2085   (when (re-search-forward "^Table [Oo]f [Cc]ontents[ \t]*$" nil t)
2086     (beginning-of-line)
2087     t))
2088
2089 ;;}}}
2090 ;;{{{ Conversions
2091
2092 ;;; ----------------------------------------------------------------------
2093 ;;;
2094 (defun tinytf-convert-preference-set ()
2095   "Set HTML conversion preferences."
2096   (interactive)
2097   (message "tinytf-convert-preference-set is not yet implemented.")
2098   (sleep-for 2))
2099
2100 ;;; ----------------------------------------------------------------------
2101 ;;;
2102 (put 'tinytf-convert-view-macro 'lisp-indent-function 0)
2103 (put 'tinytf-convert-view-macro 'edebug-form-spec '(body))
2104 (defmacro tinytf-convert-view-macro (&rest body)
2105   "Check file `tinytf-:file-last-html-generated' and run BODY."
2106   (`
2107    (let* ((file tinytf-:file-last-html-generated))
2108      (when (or (not file)
2109                (not (file-exists-p file)))
2110        (error "TinyTf: Can't view HTML, file not available [%s]"
2111               (prin1-to-string file)))
2112      (,@ body))))
2113
2114 ;;; ----------------------------------------------------------------------
2115 ;;;
2116 (defun tinytf-convert-view-default ()
2117   "View last HTML with `browse-url'."
2118   (interactive)
2119   (tinytf-convert-view-macro
2120    ;; (browse-url file)
2121    (tinyurl-agent-funcall 'url file)))
2122
2123 ;;; ----------------------------------------------------------------------
2124 ;;;
2125 (defun tinytf-convert-view-html-source ()
2126   "View last HTML with `find-file-other-window'."
2127   (interactive)
2128   (tinytf-convert-view-macro
2129    (find-file-other-window file)))
2130
2131 ;;; ----------------------------------------------------------------------
2132 ;;;
2133 (defsubst tinytf-convert-file-name-html (file)
2134   "Make FILE.txt FILE.html"
2135   (concat (file-name-sans-extension file) ".html"))
2136
2137 ;;; ----------------------------------------------------------------------
2138 ;;;
2139 (defun tinytf-convert-buffer-file-name-html-source (buffer)
2140   "Return filename from where to read plain text.
2141 For files this should be `buffer-file-name', but for buffer
2142 that are not associated with file, a temporary filename is
2143 generated using `ti::temp-file'."
2144   (or (buffer-file-name buffer)
2145       (ti::temp-file "tinytf-temp.html" 'temp-dir)))
2146
2147 ;;; ----------------------------------------------------------------------
2148 ;;;
2149 (defun tinytf-convert-html-source (&optional buffer)
2150   "Return BUFFER's source file name. Default is `current-buffer'.
2151 See `tinytf-:buffer-file-name-html-source-function'"
2152   (or (funcall
2153        tinytf-:buffer-file-name-html-source-function
2154        (or buffer
2155            (current-buffer)))
2156       (error "TinyTf: HTML source function failed.")))
2157
2158 ;;; ----------------------------------------------------------------------
2159 ;;;
2160 (defun tinytf-convert-html-destinaton (&optional buffer)
2161   "Return BUFFER's destination file name. Default is `current-buffer'.
2162 See `tinytf-:buffer-file-name-html-destination-function'"
2163   (let* ((file (funcall
2164                 tinytf-:buffer-file-name-html-destination-function
2165                 (or buffer
2166                     (current-buffer)))))
2167     (unless file
2168       (error "TinyTf: HTML destination function failed %s."
2169              (prin1-to-string
2170               tinytf-:buffer-file-name-html-destination-function)))
2171     (setq tinytf-:file-last-html-generated file)))
2172
2173 ;;; ----------------------------------------------------------------------
2174 ;;;
2175 (defsubst tinytf-file-name-html (file)
2176   "Make FILE.txt => FILE.html"
2177   (concat (file-name-sans-extension file) ".html"))
2178
2179 ;;; ----------------------------------------------------------------------
2180 ;;;
2181 (defun tinytf-convert-buffer-file-name-html-destination (buffer)
2182   "Make buffer's FILE.txt => FILE.html"
2183   (tinytf-file-name-html (buffer-file-name buffer)))
2184
2185 ;;; ----------------------------------------------------------------------
2186 ;;;
2187 (defsubst tinyperl-convert-binary-t2html ()
2188   "Return t2html.el full path."
2189   (let ((bin (get 'tinytf-mode 't2html)))
2190     (when (or (not bin)
2191               (not (file-exists-p bin)))
2192       (error
2193        (substitute-command-keys "\
2194 No t2html.pl available. Run HTML=>Conversion menu re-evaluate\
2195  \\[tinytf-utility-programs-check-force]")))
2196     bin))
2197
2198 ;;; ----------------------------------------------------------------------
2199 ;;;
2200 (put 'tinytf-convert-wrapper-macro 'lisp-indent-function 1)
2201 (put 'tinytf-convert-wrapper-macro 'edebug-form-spec '(body))
2202 (defmacro tinytf-convert-wrapper-macro (temp &rest body)
2203   "Define some common variables in `let'.
2204
2205 Variables available:
2206
2207  file-name   Buffer's file name or nil
2208  file        The filename (possibley generated) for HTML output.
2209
2210 Input:
2211
2212   TEMP       if non-nil, write temporary buffers to disk
2213   BODY       rest of the lisp forms."
2214   (`
2215    (let* ((file-name (buffer-file-name))
2216           (file      (tinytf-convert-html-source)))
2217      (when (and (, temp)
2218                 (null file-name))
2219        (let* ((buffer (current-buffer)))
2220          (with-temp-buffer
2221            (insert-buffer buffer)
2222            (write-region (point-min) (point-max) file))))
2223      (,@ body))))
2224
2225 ;;; ----------------------------------------------------------------------
2226 ;;;
2227 (defun tinytf-convert-call-process (&optional options process mode)
2228   "Convert buffer using Perl t2html.pl.
2229 In order to use this function, `tinytf-utility-programs-check' must
2230 have been called to set location of perl script.
2231
2232 The current buffer is used as source. Temporary buffers
2233 are written on disk.
2234
2235 Input:
2236
2237   OPTIONS   List of option to be passed to t2html.pl
2238             Following options are usually the minunum:
2239             '(\"--Out\" \"buffer-file-name.txt\")
2240             Nil values will be ignored.
2241
2242   PROCESS   'compile  [this is default]
2243             'call-prosess, see also MODE
2244
2245   MODE      This is only used for PROCESS 'call-process
2246             'noerr   = Do not display log on error.
2247             'display = Display the result buffer
2248             nil      = Dislpay on only if process printed something
2249                        (a possible HTML conversion error)
2250
2251 Return:
2252
2253  '(html-file-name  status).   non-nil status is an error.
2254                               Status may also be compile buffer process."
2255   (interactive)
2256   (setq options (delq nil options))
2257   (tinytf-convert-wrapper-macro 'temp-write
2258                                 (message "TinyTf: Generating HTML... (t2html) %s" file-name)
2259                                 ;;  This may take a while
2260                                 ;;  We feed the script to Perl and that works in every
2261                                 ;;  platform.
2262                                 (let* ((log    (get-buffer-create tinytf-:buffer-html-process))
2263                                        (target (tinytf-convert-html-destinaton))
2264                                        (dir    (file-name-directory target))
2265                                        (opt    (append options
2266                                                        (list
2267                                                         "--Out-dir"
2268                                                         dir
2269                                                         "--Out"
2270                                                         file)))
2271                                        status)
2272                                   (with-current-buffer log
2273                                     (insert (format "\nTinyTf: t2html.pl run %s\n"
2274                                                     (ti::date-standard-date 'minutes)))
2275
2276                                     (insert (format "Source: %s\n" file)
2277                                             (format "Target: %s\n" target))
2278                                     (cond
2279                                      ((eq process 'call-process)
2280                                       (with-temp-buffer
2281                                         (apply 'call-process "perl"
2282                                                nil
2283                                                (current-buffer)
2284                                                nil
2285                                                (tinyperl-convert-binary-t2html)
2286                                                opt)
2287                                         (message "TinyTf: Generating HTML...done. %s" target)
2288                                         (cond
2289                                          ((or (eq mode 'display)
2290                                               (and (null mode)
2291                                                    (not (ti::buffer-empty-p))))
2292                                           (setq status 'error)
2293                                           (append-to-buffer log (point-min) (point-max))
2294                                           (display-buffer log))
2295                                          ((eq mode 'noerr)
2296                                           nil))))
2297                                      (t
2298                                       (let* ((command (concat
2299                                                        "perl "
2300                                                        (tinyperl-convert-binary-t2html)
2301                                                        " "
2302                                                        " --print-url "
2303                                                        (ti::list-to-string opt))))
2304                                         (compile-internal command
2305                                                           "No more lines."
2306                                                           tinytf-:process-compile-html
2307                                                           nil nil)
2308                                         ;;  Turn on URL recognizer so that lines can be clicked
2309                                         (with-current-buffer
2310                                             (get-buffer
2311                                              (format "*%s*"
2312                                                      tinytf-:process-compile-html))
2313                                           (run-hooks 'tinytf-:process-compile-hook))
2314                                         (message "TinyTf: Generating HTML... compile. %s"
2315                                                  target))))
2316                                     (ti::append-to-buffer
2317                                      log
2318                                      (format "\nEnd: %s\n"
2319                                              (ti::date-standard-date 'minutes)))
2320                                     (list target status)))))
2321
2322 ;;; ----------------------------------------------------------------------
2323 ;;;
2324 (defsubst tinytf-convert-extra-options ()
2325   "If there is #t2html-* tag, return list of additional options."
2326   (when (ti::re-search-check "#t2html-")
2327     '("--Auto-detect")))
2328
2329 ;;; ----------------------------------------------------------------------
2330 ;;;
2331 (defun tinytf-convert-t2html-basic ()
2332   "Make 1-page HTML."
2333   (interactive)
2334   (tinytf-convert-call-process
2335    (tinytf-convert-extra-options)))
2336
2337 ;;; ----------------------------------------------------------------------
2338 ;;;
2339 (defun tinytf-convert-t2html-frame ()
2340   "Make HTML with frames using t2html.pl"
2341   (interactive)
2342   (tinytf-convert-call-process
2343    (append
2344     (tinytf-convert-extra-options)
2345     (list "--html-frame"))))
2346
2347 ;;; ----------------------------------------------------------------------
2348 ;;;
2349 (defun tinytf-convert-t2html-as-is ()
2350   "Make HTML with frames using t2html.pl"
2351   (interactive)
2352   (tinytf-convert-call-process '("--as-is")))
2353
2354 ;;; ----------------------------------------------------------------------
2355 ;;;
2356 (defun tinytf-convert-t2html-link-check (&optional options)
2357   "Call t2html.pl to check links with OPTIONS."
2358   (interactive)
2359   (tinytf-convert-wrapper-macro 'temp-write
2360                                 (let* ((command-args
2361                                         (concat "perl "
2362                                                 (tinyperl-convert-binary-t2html)
2363                                                 " "
2364                                                 (or options
2365                                                     "--link-check --quiet")
2366                                                 " "
2367                                                 file)))
2368                                   ;;  compile-internal:
2369                                   ;;    command
2370                                   ;;    error-message
2371                                   ;;    &optional
2372                                   ;;    name-of-mode
2373                                   ;;    parser
2374                                   ;;    error-regexp-alist
2375                                   ;;    name-function
2376                                   ;;    enter-regexp-alist
2377                                   ;;    leave-regexp-alist
2378                                   ;;    file-regexp-alist
2379                                   ;;    nomessage-regexp-alist
2380                                   (compile-internal command-args
2381                                                     "No more lines."
2382                                                     tinytf-:process-compile-html
2383                                                     nil
2384                                                     grep-regexp-alist))))
2385
2386 ;;; ----------------------------------------------------------------------
2387 ;;;
2388 (defun tinytf-convert-t2html-link-check-cached ()
2389   "Call t2html.pl to check links by using `tinytf-:t2html-link-cache-file'."
2390   (interactive)
2391   (unless (stringp tinytf-:t2html-link-cache-file)
2392     (error "Tinytf: `tinytf-:t2html-link-cache-file' must contain filename."))
2393   (tinytf-convert-t2html-link-check
2394    (format "--link-check --quiet --Link-cache %s"
2395            tinytf-:t2html-link-cache-file)))
2396
2397 ;;; ----------------------------------------------------------------------
2398 ;;;
2399 (defun tinytf-compile-mode-settings ()
2400   "Install font lock and additional keybindings for Link check."
2401   (let* ()))
2402              ;; #todo: font-lock
2403
2404 ;;; ----------------------------------------------------------------------
2405 ;;;
2406 (defun tinytf-convert-htmlize ()
2407   "Convert buffer using Perl htmlize.el"
2408   (interactive)
2409   (unless (fboundp 'htmlize-buffer)
2410     (error "TinyTf: `htmlize-buffer' is not available. You need htmlize.el"))
2411   (let* ((path (get 'tinytf-mode 'htmlize))
2412          (dir  (file-name-directory path))
2413          (elc  (concat dir "htmlize.elc")))
2414     (unless (file-exists-p elc)
2415       (message "TinyTf: (performance) Please compile %s" path)
2416       (sit-for 0.5)))
2417   (let* ((html-buffer "*html*") ;; Thisis in htmlize.el, but hard coded
2418          (buffer      (current-buffer)))
2419     ;; Prevent multple *html* buffers.
2420     (if (get-buffer html-buffer)
2421         (kill-buffer (get-buffer html-buffer)))
2422
2423     (tinytf-convert-wrapper-macro nil
2424                                   (message "TinyTf: Generating HTML... (htmlize) %s" file-name)
2425                                   (ti::funcall 'htmlize-buffer)
2426                                   (with-current-buffer html-buffer
2427                                     (write-region
2428                                      (point-min)
2429                                      (point-max)
2430                                      (tinytf-convert-html-destinaton buffer)))
2431                                   (message "TinyTf: Generating HTML...done. %s"
2432                                            (tinytf-convert-file-name-html file)))))
2433
2434 ;;}}}
2435 ;;{{{ misc:
2436
2437 ;;; ----------------------------------------------------------------------
2438 ;;;
2439 (defun tinytf-utility-programs-check (&optional force verb)
2440   "Set or disable found utilities (HTML converters). FORCE check.
2441 The settings will affect the main drop-down menu. If you install
2442 htmllize.el or t2html.pl to the system after package ais loaded,
2443 you must run this function.
2444
2445 Reference:
2446
2447   See (symbol-plist 'tinytf-mode)."
2448   (interactive (list t t))
2449   (let* ((sym 'tinytf-mode)
2450          ;; Affects expand-file-name to use only / in XEmacs
2451          (path-separator ?/))
2452     (when (or force
2453               (null (get sym 't2html-checked)))
2454       (let* ((path  (progn
2455                       ;;  Print messages because searching PATH may take
2456                       ;;  some time
2457                       (when verb
2458                         (message "Tinytf: searching t2html.pl..."))
2459                       (prog1
2460                           (ti::file-get-load-path "t2html.pl" exec-path)
2461                         (when verb
2462                           (message "Tinytf: searching t2html.pl... Done.")))))
2463              ;;  convert to use only forward slashes.
2464              (path2 (or tinytf-:binary-t2html path))
2465              (bin   (and path2
2466                          (file-exists-p path2)
2467                          (expand-file-name path2))))
2468         (cond
2469          (bin
2470           (put sym 't2html-checked t)
2471           (put sym 't2html bin))
2472          (verb
2473           (message "Tinytf: Cannot find t2html.pl along `exec-path'.")))))
2474     (when (or force
2475               (null (get sym 'htmlize-checked)))
2476       (let* ((path (locate-library "htmlize.el")))
2477         (cond
2478          (path
2479           (put sym 'htmlize-checked t)
2480           (put sym 'htmlize path))
2481          (verb
2482           (message "Tinytf: Cannot find htmlize.pl along `load-path'.")))))
2483     (list
2484      (get sym 'htmlize)
2485      (get sym 't2html))))
2486
2487 ;;; ----------------------------------------------------------------------
2488 ;;;
2489 (defun tinytf-utility-programs-check-force ()
2490   "Re-evaluate menu and find new conversion programs.
2491 The menu items are greyed out if the conversion programs were no
2492 available during startup. If you later install the conversion programs
2493 either to PATH or `load-path', run this function to enable menu
2494 selections.
2495
2496 This function calls `tinytf-utility-programs-check' with 'force."
2497   (interactive)
2498   (tinytf-utility-programs-check 'force 'verb))
2499
2500 ;;; ----------------------------------------------------------------------
2501 ;;;
2502 (defun tinytf-fontify-current-buffer-window ()
2503   "Fontify current buffer's window."
2504   (let* ((buffer (current-buffer))
2505          (win    (get-buffer-window buffer)))
2506     (when (and win
2507                (window-live-p win)
2508                (or font-lock-mode
2509                    global-font-lock-mode))
2510       (select-window win)
2511       (font-lock-fontify-region (window-start)
2512                                 (min (point-max) (window-end))))))
2513
2514 ;;; ----------------------------------------------------------------------
2515 ;;;
2516 (defun tinytf-untabify-buffer ()
2517   "Untabify whole buffer."
2518   (interactive "*")
2519   (when tinytf-mode
2520     (untabify (point-min) (point-max))))
2521
2522 ;;; ----------------------------------------------------------------------
2523 ;;;
2524 (defun tinytf-column-info ()
2525   "Return column intepretation."
2526   (interactive)
2527   (let* ((col (current-column))
2528          (elt (assq col tinytf-:column-table))
2529          list
2530          re
2531          ret)
2532     (when elt
2533       (setq list (nth 1 elt))
2534       (dolist (elt list)
2535         (setq re (car elt))
2536         (cond
2537          ((not (stringp re))            ;Stop there
2538           (setq ret (nth 1 elt))
2539           (return))
2540          ((looking-at re)               ;found match ?
2541           (setq ret (nth 1 elt))
2542           ;; Yes, stop there
2543           (return)))))
2544     ret))
2545
2546 ;;; ----------------------------------------------------------------------
2547 ;;;
2548 (defun tinytf-column-info-display (&optional suppress)
2549   "Display column info.
2550 This function displays information about the column and the text
2551 following it. Function does not look around the text and it will not
2552 detect text inside bullets or inside any other complex text.
2553 E.g.
2554
2555         o   *Bullet here...
2556             Continues here
2557
2558 Cursor is at [*], which is column 12, which will indicate that the column
2559 is used for code examples and marked with <SAMPLE>.
2560
2561 Input:
2562   SUPPRESS  If non-nil, do no display unneeded messages."
2563   (interactive)
2564   (let ((string (tinytf-column-info))
2565         (col    (current-column)))
2566     (if string
2567         (message "TinyTf: %s (col %d)" string col)
2568       (unless suppress
2569         (message "TinyTf: Nothing special at column %d" col)))))
2570
2571 ;;}}}
2572 ;;{{{ headings
2573
2574 ;;; ----------------------------------------------------------------------
2575 ;;;
2576 (defun tinytf-heading-positions (&optional and-heading-names)
2577   "Read heading sections forward.
2578
2579 Input:
2580
2581  AND-HEADING-NAMES  see return value.
2582
2583 Return:
2584
2585  '(pos pos ..)
2586  '((heading pos) (heading pos) ..) If AND-HEADING-NAMES is non-nil
2587  nil"
2588   (let* (point
2589          heading
2590          list)
2591     (save-excursion
2592       (tinytf-heading-macro
2593        (setq point (line-beginning-position))
2594        (cond
2595         (and-heading-names
2596          ;;  Dont read trailing spaces.
2597          (end-of-line)
2598          (if (re-search-backward "[^ \t]+" point t)
2599              ;; Search 'eats' one character include it too.
2600              (setq heading (buffer-substring point (1+ (point))))
2601            (setq heading (buffer-substring point (point))))
2602          (push (cons  heading (point)) list))
2603         (t
2604          (push (point) list)
2605          (end-of-line)))))
2606     ;;  Add point max there too. (due to hide region)
2607     (if (and list (null and-heading-names))
2608         (push (point-max) list))
2609     (nreverse list)))
2610
2611 ;;; ----------------------------------------------------------------------
2612 ;;;
2613 (defun tinytf-heading-fix-case-all (&optional confirm verb)
2614   "Convert all headings to lowercase and capitalize first word.
2615 If CONFIRM is non-nil ask permission to fix for each heading. VERB."
2616   (interactive "*P")
2617   (ti::verb)
2618   (tinytf-heading-macro
2619    (when (and (tinytf-heading-fix-case-p)
2620               (or (and
2621                    confirm
2622                    (y-or-n-p (format
2623                               "Fix? %s"
2624                               (ti::string-left
2625                                (ti::read-current-line) 70))))
2626                   (null confirm)))
2627      (downcase-region (line-beginning-position) (line-end-position))
2628      (capitalize-word 1))
2629    (end-of-line))
2630   (if verb
2631       (message "TinyTf: Case fix done.")))
2632
2633 ;;; ----------------------------------------------------------------------
2634 ;;;
2635 (defun tinytf-heading-fix-case-p ()
2636   "Check if current heading need case fixing.
2637 Caller must ensure that current line is heading. Point is moved."
2638   (beginning-of-line)
2639   (if (looking-at "[0-9. \t]+")         ;Forget heading numbering
2640       (re-search-forward "[0-9. \t]+" (line-end-position)) )
2641
2642   (or (and (looking-at "[a-z]")         ;It alphabet
2643            (let* (case-fold-search)     ;is it uppercase?
2644              (not (looking-at "[A-Z]"))))
2645       (save-excursion           ;Howabout rest of the line; lowercase?
2646         (forward-char 1)
2647         (let* (case-fold-search)
2648           (looking-at ".*[A-Z]")))))
2649
2650 ;;; ----------------------------------------------------------------------
2651 ;;;
2652 (defun tinytf-heading-fix-case ()
2653   "Write heading in lowercase and capitalize first word. Move heading forward.
2654 If current line is not a heading, do nothing.
2655
2656 Return:
2657
2658   t         if modified current and moved to next heading.
2659   nil"
2660   (interactive "*")
2661   (let* ((re  (concat (tinytf-regexp) "\\|" (tinytf-regexp 1)))
2662          ret)
2663     (when (save-excursion
2664             (beginning-of-line)
2665             (looking-at re))
2666       (when (tinytf-heading-fix-case-p)
2667         (downcase-region (line-beginning-position) (line-end-position))
2668         (capitalize-word 1)
2669         (setq ret t)))
2670     ret))
2671
2672 ;;; ----------------------------------------------------------------------
2673 ;;;
2674 (defun tinytf-heading-fix-newlines (&optional verb)
2675   "Search all headings and remove extra newlines. VERB.
2676
2677 Return:
2678
2679   nil       nothing fixed
2680   nbr       this many fixed."
2681   (interactive "*")
2682   (let  ((mark   (point-marker))        ;Heading start point
2683          (fix    0)
2684          beg)
2685     (ti::verb)
2686     (tinytf-heading-macro
2687      (move-marker mark (point))
2688      (forward-line  -1)
2689      (setq beg (point))
2690      ;;  Delete previous newlines
2691      (unless (bobp)
2692        (cond
2693         ((not (looking-at "^[ \t]*$"))  ;no whitespace at all
2694          (end-of-line) (insert "\n") (incf  fix))
2695         ((not (zerop (skip-chars-backward " \t\r\n"))) ;extra whitespace
2696          (forward-line 1)
2697          (delete-region beg (point)) (incf  fix))))
2698      (goto-char (marker-position mark))
2699      (forward-line 1)
2700      (setq beg (point))
2701      (unless (eobp)
2702        (cond
2703         ((not (looking-at "^[ \t]*$"))  ;no whitespace at all
2704          (beginning-of-line)
2705          (insert "\n")
2706          (incf  fix))
2707         ((not (zerop (skip-chars-forward " \t\r\n"))) ;extra whitespace
2708          (beginning-of-line)
2709
2710          ;;   Skip chars forward for to next line in following case,
2711          ;;   see the (*) cursor position. When we do beginning of
2712          ;;   line; the point is 1+ BEG, but we really don't want
2713          ;;   to delete that region!
2714          ;;
2715          ;;   Header 1
2716          ;;
2717          ;;     (*)Sub header 2
2718          (when (not (memq (point) (list beg (1+ beg))))
2719            (delete-region beg (point))
2720            (incf  fix))))))
2721     (setq mark nil)                     ;kill marker
2722     (if verb
2723         (if (> fix 0)
2724             (message "TinyTf: fixed %d places around headings" fix)
2725           (message "TinyTf: no newline fixes.")))
2726
2727     (if (> fix 0)                       ;anything to return?
2728         fix)))
2729
2730 ;;; ----------------------------------------------------------------------
2731 ;;;
2732 (defun tinytf-heading-fix (&optional verb)
2733   "Search all headings and convert first letter to uppercase if needed. VERB.
2734 This function will only chnage the first word in the heading, no
2735 other case conversions are done."
2736   (interactive "*P")
2737   (let* ((re  (concat                   ;Search lower letters only
2738                "^" (tinytf-heading-number-regexp) "?"
2739                "[a-z]"
2740
2741                "\\|^" (tinytf-indent 1)
2742                (tinytf-heading-number-regexp) "?"
2743                "[a-z]"))
2744          (count  0)
2745          case-fold-search)
2746     (ti::verb)
2747     (save-excursion
2748       (ti::pmin)
2749       (while (re-search-forward re nil t)
2750         (backward-char 1)
2751         (capitalize-word 1)
2752         (incf  count)))
2753     (if verb
2754         (message "%s: Fixed %d headings" tinytf-:mode-name count))))
2755
2756 ;;; ----------------------------------------------------------------------
2757 ;;;
2758 (defun tinytf-heading-numbering (&optional remove verb)
2759   "Number heading levels. Old numbering is replaced.
2760 Optionally REMOVE numbering. VERB."
2761   (interactive "*P")
2762   (let* ((re-no-nbr2 (if (> tinytf-:heading-number-level 0)
2763                          (tinytf-regexp 1)))
2764          (re-no-nbr3 (if (> tinytf-:heading-number-level 1)
2765                          (tinytf-regexp 2)))
2766          (re-nbr    (tinytf-heading-number-regexp))
2767          (re1       (concat "^" (tinytf-indent 0) re-nbr))
2768          (re2       (if (> tinytf-:heading-number-level 0)
2769                         (concat "^" (tinytf-indent 1) re-nbr)))
2770          (re3       (if (> tinytf-:heading-number-level 1)
2771                         (concat "^" (tinytf-indent 2) re-nbr)))
2772          (c1        0)                  ;counters
2773          (c2        0)
2774          (c3        0)
2775          (count     0)
2776          (fix       0)
2777          str)
2778     (ti::verb)
2779     (tinytf-heading-macro
2780      (incf  count)
2781      (beginning-of-line)
2782      (cond
2783       (remove
2784        (if (or (looking-at re1)
2785                (and re2
2786                     (looking-at re2))
2787                (and re3
2788                     (looking-at re3)))
2789            (ti::replace-match 1)))
2790       ((looking-at re1)                 ;heading 1
2791        (incf c1)
2792        (setq c2 0)
2793        (setq str (tinytf-heading-string c1 c2))
2794        ;;  Only change if different, this prevents buffer modify flag
2795        ;;  change
2796        (unless (tinytf-heading-same-p 0 str)
2797          (incf  fix)
2798          (ti::replace-match 1 str)))
2799       ((and re2 (looking-at re2))
2800        (incf c2)
2801        (setq c3 0)
2802        (setq str (tinytf-heading-string c1 c2))
2803        (unless (tinytf-heading-same-p 1 str)
2804          (incf  fix)
2805          (ti::replace-match 1 str)))
2806       ((and re3 (looking-at re3))
2807        (incf c3)
2808        (setq str (tinytf-heading-string c1 c2 c3))
2809        (unless (tinytf-heading-same-p 2 str)
2810          (incf  fix)
2811          (ti::replace-match 1 str)))
2812       ((and re-no-nbr2
2813             (looking-at re-no-nbr2))    ;Level 2
2814        (goto-char (match-end 0))
2815        (backward-char 1)
2816        (incf  c2)
2817        (insert (tinytf-heading-string c1 c2)))
2818       ((and re-no-nbr3
2819             (looking-at re-no-nbr3))    ;Level 2
2820        (goto-char (match-end 0))
2821        (backward-char 1)
2822        (incf  c3)
2823        (insert (tinytf-heading-string c1 c2 c3)))
2824       ((looking-at "^")                 ;must be level 1
2825        (setq c2 0)     (incf  c1)
2826        (incf  fix)
2827        (insert (tinytf-heading-string c1 c2))))
2828      (end-of-line))
2829     (when verb
2830       (message "%s: %d/%d headings numbered."
2831                tinytf-:mode-name fix count))))
2832
2833 ;;; ----------------------------------------------------------------------
2834 ;;;
2835 (defun tinytf-fix-all (&optional verb)
2836   "Fix headers, untabify buffer and do other things. VERB.
2837
2838 Note:
2839
2840   This function does not call following functions:
2841
2842   `tinytf-heading-fix-case-all', because you are in charge of the case of
2843   headings. Only first letter is made uppercase.
2844
2845   `tinytf-toc', because the TOC in the buffer would always be substituted.
2846   and this would mark buffer modified although no other changes were made.
2847   Update this manually after heading changes.
2848
2849 References:
2850
2851   `tinytf-:fix-all-hook'   Well, you can do the misisng things here."
2852   (interactive "*")
2853   (ti::verb)
2854   ;;  when you fill paragraphs, the default Emacs has nasty habits to
2855   ;;  end the sentece to two spaces, which is some idiot way to separate
2856   ;;  two sentences (the history says that the typewriter fonts were so bad
2857   ;;  that the typists needed to add two spaces these).
2858   ;;
2859   ;;  Fix them to have only standard space.
2860   (if verb
2861       (message "TinyTf: Fixing double spaces..."))
2862   (save-excursion
2863     (ti::pmin)
2864     (while (re-search-forward "[a-zA-Z]+[!?.,]\\(  +\\)[a-zA-Z]+" nil t)
2865       (ti::replace-match 1 " ")))
2866   (if verb
2867       (message "TinyTf: Trimming extra blank lines..."))
2868   (ti::buffer-trim-blanks (point-min) (point-max)) ;Remove trailing blanks
2869   (if verb
2870       (message "TinyTf: Heading fix..."))
2871   (tinytf-heading-fix)
2872   (tinytf-untabify-buffer)
2873   (tinytf-heading-fix-newlines)
2874   (if verb
2875       (message "TinyTf: Checking heading numbering..."))
2876   (when (tinytf-headings-numbered-p)
2877     (tinytf-heading-numbering))
2878   (if verb
2879       (message "TinyTf: Running user fix hooks..."))
2880   (run-hooks 'tinytf-:fix-all-hook)
2881   (if verb
2882       (message "TinyTf: Fixing done.")))
2883
2884 ;;}}}
2885 ;;{{{ text: formatting with codes
2886
2887 ;;; ----------------------------------------------------------------------
2888 ;;;
2889 (defun tinytf-paragraph-first-line-indent-fix (col)
2890   "Make sure the first line in the paragraph start at column COL.
2891 point must be inside paragraph before calling function."
2892   ;;  After fill; the first line may still be ragged. fix it
2893   ;;
2894   ;;      txt txt txt txt
2895   ;;  txt txt txt txt txt
2896   ;;  txt txt txt txt txt
2897   (if (string-match "^[ \t]$" (ti::read-current-line))
2898       (error "Must be inside text."))
2899   (when (re-search-backward "^[ \t]*$" nil t)
2900     (forward-line 1)
2901     (skip-chars-forward " \t")
2902     (unless (eq col (current-column))
2903       (delete-region (point) (line-beginning-position))
2904       (insert (make-string col ?\ )))))
2905
2906 ;;; ----------------------------------------------------------------------
2907 ;;;
2908 (defun tinytf-move-paragraph-to-column (beg end col &optional msg noask)
2909   "If region BEG END is big, ask confirmation for COL move with MSG NOASK.
2910 Return
2911   (beg . end)    Region bounds now."
2912   (let* ((lines (+ (count-char-in-region beg end ?\r)
2913                    (count-char-in-region beg end ?\n)))
2914          (max   40))
2915     ;;  We use markers, because the points have moved after the
2916     ;;  call to ti::buffer-move-paragraph-to-column. We must pass moved BEG end
2917     ;;  to hook functions.
2918     (ti::keep-lower-order beg end)
2919     (save-excursion
2920       (goto-char beg)
2921       (setq beg (point-marker))
2922       (goto-char end)
2923       (setq end (point-marker)))
2924     (when (or noask
2925               (< lines (1+ max))
2926               (and
2927                (> lines max)
2928                (y-or-n-p (format "%s: really move %d lines? "
2929                                  tinytf-:mode-name lines))))
2930       (ti::buffer-move-paragraph-to-column
2931        (marker-position beg) (marker-position end)
2932        col)
2933       (if (and (null noask) (< col 12))
2934           (let ((fill-prefix (make-string col ?\ ))
2935                 (left-margin 0))
2936             (call-interactively 'fill-paragraph)))
2937       (if msg
2938           (message "TinyTf:%s" msg))
2939
2940       (run-hook-with-args 'tinytf-:move-paragraph-hook
2941                           (marker-position beg) (marker-position end))
2942       (cons beg end))))
2943
2944 ;;; ----------------------------------------------------------------------
2945 ;;;
2946 (tinytf-fmacro-indent-region
2947  tinytf-indent-region-text
2948  "Move selected region to STRONG html code position."
2949  8 (format "TinyTf: Regular text, column 8"))
2950
2951 (tinytf-fmacro-indent-region
2952  tinytf-indent-region-strong
2953  "Move selected region to STRONG html code position."
2954  9 (format "TinyTf: Strong, column 9"))
2955
2956 (tinytf-fmacro-indent-region
2957  tinytf-indent-region-quote
2958  "Move selected region to EMPHATISED (quoted text) html code position."
2959  10 (format "TinyTf: Quotation, column 10"))
2960
2961 (tinytf-fmacro-indent-region
2962  tinytf-indent-region-sample
2963  "Move selected region to SAMPLE (example code) html code position."
2964  12 (format "TinyTf: Sample, column 12"))
2965
2966 ;;; ----------------------------------------------------------------------
2967
2968 (tinytf-fmacro-indent-paragraph
2969  tinytf-indent-paragraph-zero
2970  "Move paragraph to column 0."
2971  0 (format "TinyTf: Zero, column 0"))
2972
2973 (tinytf-fmacro-indent-paragraph
2974  tinytf-indent-paragraph-2
2975  "Move paragraph to column 2."
2976  2 (format "TinyTf: column 2"))
2977
2978 (tinytf-fmacro-indent-paragraph
2979  tinytf-indent-paragraph-3
2980  "Move paragraph to column 3."
2981  3 (format "TinyTf: column 3"))
2982
2983 (tinytf-fmacro-indent-paragraph
2984  tinytf-indent-paragraph-5
2985  "Move paragraph to column 5."
2986  5 (format "TinyTf: column 5"))
2987
2988 (tinytf-fmacro-indent-paragraph
2989  tinytf-indent-paragraph-6
2990  "Move paragraph to column 6."
2991  6 (format "TinyTf: column 6")
2992  (progn
2993    (fill-paragraph nil)
2994    (tinytf-forward-paragraph)))
2995
2996 (tinytf-fmacro-indent-paragraph
2997  tinytf-indent-paragraph-11
2998  "Move paragraph to column 11."
2999  11 (format "TinyTf: column 11"))
3000
3001 (tinytf-fmacro-indent-paragraph
3002  tinytf-indent-paragraph-text
3003  "Move paragraph to text position."
3004  8 (format "TinyTf: text, column 8")
3005  (progn
3006    (tinytf-forward-paragraph)))
3007
3008 (tinytf-fmacro-indent-paragraph
3009  tinytf-indent-paragraph-text-as-is
3010  "Move paragraph to text position."
3011  8 (format "TinyTf: text, column 8")
3012  (progn
3013    (tinytf-forward-paragraph)))
3014
3015 (tinytf-fmacro-indent-paragraph
3016  tinytf-indent-paragraph-text-and-fill
3017  "Move paragraph to text position and fill."
3018  8 (format "TinyTf: text, column 8")
3019  (let* ((fill-prefix
3020          (or (ti::string-match "^[ \t]+" 0 (ti::read-current-line))
3021              ""))
3022         (left-margin 0))
3023    (fill-paragraph nil)
3024    (tinytf-paragraph-first-line-indent-fix 8)
3025    (tinytf-forward-paragraph)))
3026
3027 (tinytf-fmacro-indent-paragraph
3028  tinytf-indent-paragraph-quote
3029  "Move paragraph to Quotation position."
3030  10 (format "TinyTf: Quotation, column 10"))
3031
3032 (tinytf-fmacro-indent-paragraph
3033  tinytf-indent-paragraph-quote-and-fill
3034  "Move paragraph to Quotation position and fill."
3035  10 (format "TinyTf: Quotation, column 10")
3036  (let* ((fill-prefix (or (ti::string-match
3037                           "^[ \t]+"
3038                           0
3039                           (ti::read-current-line))
3040                          ""))
3041         (left-margin 0))
3042    (fill-paragraph nil)
3043    (tinytf-paragraph-first-line-indent-fix 10)
3044    (tinytf-forward-paragraph)))
3045
3046 (tinytf-fmacro-indent-paragraph
3047  tinytf-indent-paragraph-sample
3048  "Move paragraph to Sample code position."
3049  12 (format "TinyTf: Sample, column 12")
3050  (progn
3051    (tinytf-forward-paragraph)))
3052
3053 ;;; ----------------------------------------------------------------------
3054 ;;;
3055 (tinytf-fmacro-mark-word
3056  tinytf-mark-word-sample
3057  "Put 'SAMP' code around word and move forward." ?` ?' )
3058
3059 (tinytf-fmacro-mark-word
3060  tinytf-mark-word-emp
3061  "Put 'EM' code around word and move forward." ?* )
3062
3063 (tinytf-fmacro-mark-word
3064  tinytf-mark-word-strong
3065  "Put 'STRONG' code around word and move forward." ?_ )
3066
3067 (tinytf-fmacro-mark-word
3068  tinytf-mark-word-big
3069  "Put 'BIG' code around word and move forward." ?+ )
3070
3071 (tinytf-fmacro-mark-word
3072  tinytf-mark-word-small
3073  "Put 'SMALL' code around word and move forward." ?= )
3074
3075 ;;; ----------------------------------------------------------------------
3076 ;;;
3077 (defun tinytf-unmark-word ()
3078   "Remove 'STRONG' and 'EMP' mark from word and move forward."
3079   (interactive "*")
3080   (let* ((word-skip "^ ,.;\n\r\t\f")
3081          beg
3082          end)
3083     (flet ((marker   (beg skip)
3084                      (save-excursion
3085                        (skip-chars-forward skip)
3086                        (list
3087                         (buffer-substring beg (point))
3088                         (point))))
3089            (markup-p (word)
3090                      (string-match "[_*='`]+\\([^_*='`]+\\)[_*='`]+$" word)))
3091       (unless (looking-at "[ \t\f]")
3092         (skip-chars-backward "^ ,\n\r\t\f")
3093         (setq beg (point))
3094         ;;  It depends how the markup has been done:
3095         ;;
3096         ;;      This _sentence._ And new sentence.
3097         ;;      This _sentence_. And new sentence.
3098         (dolist (try (list "^ \n\r\t\f" word-skip))
3099           (multiple-value-bind (word end)
3100               (marker beg try)
3101             (when (string-match "[_*='`]+\\([^_*='`]+\\)[_*='`]+$" word)
3102               (setq word (match-string 1 word))
3103               (delete-region beg end)
3104               (insert word)
3105               (setq end (point))
3106               (return))))
3107         (unless end
3108           (skip-chars-forward word-skip))
3109         (skip-chars-forward " (){}<>,.;:!?\"\'\n\r\t\f")))))
3110
3111 ;;; ----------------------------------------------------------------------
3112 ;;;
3113 (defun tinytf-mark-br-line (&optional unmark &optional verb)
3114   "Mark current line with symbolic <BR>. Optionally UNMARK. VERB."
3115   (interactive "*P")
3116   (let* (point
3117          ch)
3118     (ti::verb)
3119     (save-excursion
3120       (beginning-of-line)
3121       (if (not (looking-at "[ \t]+[^\r\n]"))
3122           (if verb
3123               (message "TinyTf: There must be empty spaces before line."))
3124         (setq point (match-end 0))))
3125     (when point
3126       (goto-char (1- point))
3127       (setq ch (following-char))
3128       (if unmark
3129           (if (char= ch ?.)
3130               (delete-char 1))
3131         (if (char= ch ?.)
3132             (if verb
3133                 (message "TinyTf: Already marked as <BR>"))
3134           (insert "."))))
3135     (forward-line 1)
3136     (skip-chars-forward " \t\r\n")))
3137
3138 ;;; ----------------------------------------------------------------------
3139 ;;;
3140 (defun tinytf-mark-br-paragraph (&optional unmark)
3141   "Mark current paragraph with symbolic <BR> codes. Optionally UNMARK."
3142   (interactive "*P")
3143   (let* (beg
3144          end-mark)
3145     (tinytf-backward-paragraph)
3146     (setq beg (point))
3147     (tinytf-forward-paragraph)
3148     (setq end-mark (point-marker))
3149     (goto-char beg)
3150     (while (< (point) (marker-position end-mark))
3151       (tinytf-mark-br-line unmark))
3152     ;; Kill marker
3153     (setq end-mark nil)))
3154
3155 ;;}}}
3156 ;;{{{ Formatting, misc
3157
3158 ;;; ----------------------------------------------------------------------
3159 ;;;
3160 (defun tinytf-bullet-format ()
3161   "Reformat following bullet into Technical text bullet.
3162 Point sits somewhere in current bullet. Bullets accepted are:
3163
3164     . text here
3165     + text here
3166     * text here
3167     - text here
3168     o text here
3169
3170 If the bullet strarts with 'o' or '.', then that is used as bullet
3171 mark. In all other cases 'o' is used."
3172   (interactive "*")
3173   (let* ((bullet-re     "^[ \t]*\\([-*o.+]\\)[ \t]")
3174          (para-re       (concat bullet-re "\\|^[ \t]*$"))
3175          (left-margin   0)
3176          (char          "o")
3177          (str           "            ") ;; 8 + 4 spaces
3178          fill-prefix ;; Otherwise formatting won't work right
3179          beg
3180          end)
3181     (if (not (looking-at bullet-re))
3182         (re-search-backward para-re))
3183     (beginning-of-line)
3184     (if (not (looking-at bullet-re))
3185         (re-search-forward bullet-re))
3186     ;;   Set the bullet character
3187     (setq char (match-string 1))
3188     (if (not (member char '("o" ".")))
3189         (setq char "o"))
3190     (goto-char (match-end 0))           ;Over the bullet marker
3191     ;;  Delete [WHITE-SPACE]-   text
3192     (delete-region (point) (line-beginning-position))
3193     (setq beg (point))
3194     ;;  handle continuing line
3195     ;;
3196     ;;  -   text
3197     ;;      text text
3198     (while (and (not (looking-at bullet-re))
3199                 (looking-at "[ \t]*[^ \t\r\n]"))
3200       (fixup-whitespace)
3201       (forward-line 1))
3202     (setq end (point))
3203     (ti::narrow-safe beg end
3204       ;;  Now indent the text, then fill, and finally fix the
3205       ;;  bullet start
3206       (goto-char (point-min))
3207       (setq fill-prefix str)
3208       (indent-rigidly (point-min) (point-max) (+ 8 4))
3209       (call-interactively 'fill-paragraph)
3210       (goto-char (point-min))
3211       (fixup-whitespace)
3212       (insert "        " char "   ")
3213       (setq end (point-max)))
3214     (goto-char end)
3215     ;;  Next paragraph
3216     (if (string-match "^[ \t\r\n]*$" (ti::read-current-line))
3217         (re-search-forward "^[ \t]*[^ \t\r\n]" nil t))))
3218
3219 ;;}}}
3220 ;;{{{ movement
3221
3222 ;;; ----------------------------------------------------------------------
3223 ;;;
3224 (defun tinytf-backward-paragraph ()
3225   "Like `tinytf-forward-paragraph' but go backward."
3226   (interactive)
3227   (tinytf-paragraph-macro
3228    (backward-paragraph)
3229    (backward-paragraph)
3230    (skip-chars-forward " \t\r\n")
3231    (tinytf-goto-non-space)))
3232
3233 ;;; ----------------------------------------------------------------------
3234 ;;;
3235 (defun tinytf-forward-paragraph ()
3236   "Like `forward-paragraph' but keep cursor at the beginning of text."
3237   (interactive)
3238   (tinytf-paragraph-macro
3239    (forward-paragraph)
3240    (skip-chars-forward " \t\r\n")
3241    (tinytf-goto-non-space)))
3242
3243 ;;; ----------------------------------------------------------------------
3244 ;;;
3245 (defun tinytf-heading-start ()
3246   "Goto first heading, excluding TOC heading."
3247   (interactive)
3248   (when (tinytf-toc-goto)
3249     (tinytf-heading-forward-0)))
3250
3251 ;;; ----------------------------------------------------------------------
3252 ;;;
3253 (defun tinytf-forward (level &optional back any)
3254   "Go to next heading. Optionally search LEVEL or BACK or ANY level.
3255
3256 Return:
3257
3258  nbr    point if moved
3259  nil"
3260   (let* ((re (if any
3261                  (concat (tinytf-regexp) "\\|" (tinytf-regexp 1))
3262                (tinytf-regexp level)))
3263          case-fold-search               ;case sensitive
3264          point)
3265     (if back
3266         (when (re-search-backward re nil t)
3267           (skip-chars-forward " \t") (point))
3268       (cond
3269        ((bolp)                         ;Startt seaching from next char
3270         (save-excursion
3271           (forward-char 1)
3272           (if (re-search-forward re nil t)
3273               (setq point (point))))
3274         (if point                       ;If search ok, then move
3275             (goto-char (1- point))))
3276        (t
3277         (when (re-search-forward re nil t)
3278           (backward-char 1) (point)))))))
3279
3280 ;;; ----------------------------------------------------------------------
3281 ;;;
3282 (defun tinytf-heading-forward-0 ()
3283   "Forward."
3284   (interactive)
3285   (tinytf-forward 0))
3286
3287 (defun tinytf-heading-forward-1 ()
3288   "Forward."
3289   (interactive)
3290   (tinytf-forward 1))
3291
3292 (defun tinytf-heading-forward-any ()
3293   "Forward."
3294   (interactive)
3295   (tinytf-forward 1 nil 'any))
3296
3297 (defun tinytf-heading-backward-0 ()
3298   "Backward."
3299   (interactive)
3300   (tinytf-forward 0 'back))
3301
3302 (defun tinytf-heading-backward-1 ()
3303   "Backward."
3304   (interactive)
3305   (tinytf-forward 1 'back))
3306
3307 (defun tinytf-heading-backward-any ()
3308   "Backward."
3309   (interactive)
3310   (tinytf-forward 1 'back 'any))
3311
3312 ;;}}}
3313 ;;{{{ outline control: show/hide
3314
3315 ;;; ----------------------------------------------------------------------
3316 ;;;
3317 (defun tinytf-hide-region (beg end &optional show)
3318   "Hide region BEG END with selective display. Optionally SHOW.
3319 Point is END after function finishes."
3320   (let (buffer-read-only
3321         (ch1   (if show ?\r ?\n))
3322         (ch2   (if show ?\n ?\r)))
3323     (subst-char-in-region beg end ch1 ch2)
3324     (set-buffer-modified-p nil)
3325     (goto-char (max beg end))))
3326
3327 ;;; ----------------------------------------------------------------------
3328 ;;;
3329 (defun tinytf-mouse-context-sensitive (event)
3330   "If `mouse-point' points indent 0 or 1 line, then hide/show level. EVENT.
3331 In other places call original function."
3332   (interactive "e")
3333
3334   (mouse-set-point event)
3335   (beginning-of-line)
3336   (cond
3337    ((or (tinytf-level-p 0)
3338         (tinytf-level-p 1))
3339     (tinytf-show-toggle))
3340    (t
3341     (ti::compat-mouse-call-original 'tinytf-mode event))))
3342
3343 ;;; ----------------------------------------------------------------------
3344 ;;;
3345 (defun tinytf-show-buffer ()
3346   "Remove selective display codes from buffer."
3347   (interactive)
3348   (save-excursion
3349     (tinytf-hide-region (point-min) (point-max) 'show)))
3350
3351 ;;; ----------------------------------------------------------------------
3352 ;;;
3353 (defun tinytf-hide-buffer ()
3354   "Hide whole buffer."
3355   (interactive)
3356   ;;  Save current point
3357   (let ((point (line-beginning-position)))
3358     (goto-char (point-min))
3359     (if (tinytf-level-p 0)
3360         (tinytf-hide))
3361     (while (tinytf-heading-forward-0)
3362       (tinytf-hide))
3363     ;;  But after collapsing buffer, the point is not exactly there
3364     ;;  any more => Go to the nearest heading which is at the beginning of
3365     ;;  line.
3366     (goto-char point)
3367     (goto-char (line-beginning-position))))
3368
3369 ;;; ----------------------------------------------------------------------
3370 ;;;
3371 (defun tinytf-show-toggle ()
3372   "Open/close level 1. Does't touch level 0."
3373   (interactive)
3374   (let* ((point  (point)))
3375     (if (looking-at ".*\r")
3376         (tinytf-show)            ;level is already collapsed, open it.
3377       (tinytf-hide))
3378     (goto-char point)
3379     (tinytf-goto-non-space)))
3380
3381 ;;; ----------------------------------------------------------------------
3382 ;;;
3383 (defun tinytf-show ()
3384   "Show current level."
3385   (interactive)
3386   (tinytf-hide 'show))
3387
3388 ;;; ----------------------------------------------------------------------
3389 ;;;
3390 (defun tinytf-hide (&optional show)
3391   "Hide current level. Optionally SHOW."
3392   (interactive "P")
3393   (let* ((ok    t)
3394          (point (point)))
3395     (tinytf-level-macro
3396      (cond
3397       ((eq 1 level)
3398        (tinytf-hide-region (point) (tinytf-block-end) show))
3399       (t
3400        (tinytf-hide-region (point) end show)
3401        (setq ok (tinytf-heading-forward-any))
3402        (while (and ok
3403                    ;;  Until next level 0 ...
3404                    (not (eq 0 (tinytf-level-number))))
3405          (setq beg (point))
3406          (cond
3407           ((setq ok (tinytf-heading-forward-any))
3408            (beginning-of-line) (backward-char 1)
3409            (if show
3410                (subst-char-in-region beg (point) ?\r ?\n)
3411              (subst-char-in-region beg (point) ?\n ?\r))
3412            (forward-char 1))
3413           (t
3414            (tinytf-hide-region beg (point-max)))))
3415        (set-buffer-modified-p nil)
3416        (goto-char point))))))
3417
3418 ;;}}}
3419 ;;{{{ misc: toc, exit
3420
3421 ;;; ----------------------------------------------------------------------
3422 ;;;
3423 (defun tinytf-toc-p ()
3424   "Check if there is heading \"Table of contents\".
3425 Return:
3426   (beg . end)    begin toc body, end of toc body
3427   nil"
3428
3429   (let* ((re  (concat                   ;May be Heading 1 or 2
3430                "^\\("
3431                (tinytf-indent 1)
3432                "\\)?Table [Oo]f [Cc]ontents[ \t]*$"))
3433          case-fold-search               ;is sensitive
3434          beg
3435          end)
3436     (save-excursion
3437       (ti::pmin)
3438       (when (re-search-forward re nil t)
3439         (forward-line 1) (setq beg (point))
3440         ;;  - If the above command doesn't move; assume that the Toc
3441         ;;    has been placed to the end of buffer.
3442         ;;  - maybe there is nothing more that toc or toc is at
3443         ;;    the end where there is no more headings
3444         (if (null (tinytf-heading-forward-any)) ;Not moved?
3445             (ti::pmax))                 ;go to end of buffer then
3446         (beginning-of-line)
3447         (setq end (point))
3448         (cons beg end)))))
3449
3450 ;;; ----------------------------------------------------------------------
3451 ;;;
3452 (defun tinytf-toc-mouse (event)
3453   "Create heading x-popup with mouse EVENT."
3454   (interactive "e")
3455   (tinytf-toc event))
3456
3457 ;;; ----------------------------------------------------------------------
3458 ;;;
3459 (defun tinytf-toc-occur ()
3460   "Generate Heading  occur menu."
3461   (interactive)
3462   (save-excursion
3463     (ti::pmin)
3464     (let ((toc  (tinytf-toc-p)))        ;Skip TOC
3465       (if toc
3466           (goto-char (cdr toc))))
3467     (occur "^[^ \t\r\n<#]\\|^    [^ \t\r\n]")))
3468
3469 ;;; ----------------------------------------------------------------------
3470 ;;;
3471 (defun tinytf-toc (&optional arg verb)
3472   "Create table of contents.
3473 If there is heading level 1 whose name is \"Table of Contents\",
3474 update that. If there is no such heading, then show toc in separate
3475 buffer
3476
3477 Input ARG can be:
3478
3479  nil        create toc, possibly to separate buffer
3480  \\[universal-argument]      create toc occur
3481  other      must be mouse event, create x-popup toc
3482
3483 VERB enables verbose messages."
3484   (interactive "P")
3485   (let* ((hlist     (tinytf-heading-positions 'strings))
3486          (toc       (tinytf-toc-p))
3487          (buffer    tinytf-:buffer-heading)
3488          elt)
3489     (ti::verb)
3490     (if (null hlist)
3491         (if verb
3492             (message "TinyTf: No headings found"))
3493       (cond
3494        ;; ..................................... generate toc to (text) ...
3495        ((null arg)
3496         (setq buffer (ti::temp-buffer buffer 'clear))
3497         (with-current-buffer buffer
3498           (dolist (elt hlist)
3499             (setq elt (car elt))
3500             (if (string-match "^[ \t]+" elt)
3501                 (insert elt "\n")       ;sub heading...
3502               (insert "\n" elt "\n")))
3503           (insert "\n") ;; Final newline
3504           (ti::pmin)
3505           (ti::buffer-trim-blanks (point-min) (point-max))
3506           (if (stringp tinytf-:heading-ignore-regexp-form)
3507               (flush-lines tinytf-:heading-ignore-regexp-form))
3508           ;; Make sure there are two newlines at the end so that
3509           ;; inserted TOC is positioned nicely
3510           ;; (ti::pmax)
3511           ;; (when (and (looking-at "^$")
3512           ;;            (save-excursion
3513           ;;              (forward-line -1)
3514           ;;              (not (looking-at "^$"))))
3515           ;;   (insert "\n"))
3516           ;;  Delete leading whitespace
3517           ;;  1997-08 Disabled for now and now makes:
3518           ;;
3519           ;;  1.1
3520           ;;    1.2
3521           ;;  2.0
3522           ;;    2.1
3523           ;;
3524           (when (and toc nil)
3525             ;;  Convert heading 2 level to heading  1
3526             (ti::pmin) (replace-string (tinytf-indent 1) ""))
3527           (ti::pmin)
3528           (delete-region
3529            (point)
3530            (progn
3531              (if (zerop (skip-chars-forward " \t\r\n"))
3532                  (point)
3533                (1- (point)))))
3534           ;; Make indentation to text column
3535           (when toc
3536             (string-rectangle
3537              (point-min)
3538              (point-max)
3539              (tinytf-indent 2)))) ;; with-current
3540         (cond
3541          (toc                           ;Update existing toc
3542           (barf-if-buffer-read-only)
3543           (delete-region (car toc) (cdr toc))
3544           (ti::save-with-marker-macro
3545             ;;  Leave one empty line
3546             (goto-char (car toc))
3547             (insert-buffer buffer)))
3548          (t                             ;No previous toc
3549           (when verb
3550             (pop-to-buffer buffer)
3551             (ti::pmin)))))              ;end cond inner
3552        ;; ......................................... create toc (occur) ...
3553        ((equal arg '(4))
3554         (ti::occur-macro (concat (tinytf-regexp) "\\|" (tinytf-regexp 1))))
3555        ;; ......................................... create toc (mouse) ...
3556        (t
3557         ;; ARG must be mouse-event
3558         (if (null (ti::compat-window-system))
3559             (message "TinyTf: Window system required to use popup menu")
3560           (when (setq elt
3561                       (cond
3562                        ((< (length hlist)  20)
3563                         (ti::compat-popup
3564                          (nreverse (mapcar 'car hlist))
3565                          arg nil "Headings"))
3566                        ((fboundp 'imenu--mouse-menu)
3567                         ;; It's too long to be displayed in one x-widget.
3568                         ;; Use imenu
3569                         (car-safe (ti::funcall
3570                                    'imenu--mouse-menu hlist arg)))
3571                        (t
3572                         (message
3573                          "Tinytf: X-popup not available, no imenu.el")
3574                         nil)))
3575             (let* ((ret (assoc elt hlist))
3576                    (pos (cdr-safe ret)))
3577               (if pos
3578                   (goto-char pos)
3579                 (ti::pmin)
3580                 (tinytf-toc-goto)
3581                 (tinytf-heading-forward-0)
3582                 (re-search-forward elt))))))))
3583     (if verb
3584         (message "TinyTf: TOC generated."))))
3585
3586 ;;; ----------------------------------------------------------------------
3587 ;;;
3588 (defun tinytf-exit ()
3589   "Run `tinytf-fix-all' and exit mode."
3590   (interactive)
3591   (tinytf-fix-all)
3592   (tinytf-mode 0))
3593
3594 ;;}}}
3595
3596 (unless tinytf-:mode-define-keys-hook ;; Set default setup
3597   (ti::add-hooks
3598    'tinytf-:mode-define-keys-hook
3599    '(tinytf-mode-define-keys tinytf-mode-define-f-keys)))
3600
3601 ;; It's important that this is as fast as possible
3602
3603 (ti::byte-compile-defun-maybe '(tinytf-code-p))
3604
3605 (tinytf-install)
3606
3607 (provide   'tinytf)
3608 (run-hooks 'tinytf-:load-hook)
3609
3610 ;;; tinytf.el ends here