home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 4 Drivers / 04-Drivers.zip / mtek004.zip / tkscan < prev    next >
Text File  |  1997-09-16  |  80KB  |  2,230 lines

  1. #!/bin/sh
  2. # the next line restarts using wish \
  3. exec wish "$0" "$@"
  4.  
  5. # TkScan Version and Date
  6. set c(version)     "0.8"
  7. set c(date)        "May 1997"
  8.  
  9. #----------------------------------------------------------------
  10. # About TkScan
  11. #----------------------------------------------------------------
  12. set about_tkscan "
  13. TkScan
  14. Version $c(version), $c(date)\n
  15. A tcl/tk GUI for command-line scanner driver
  16. Written by Hang-Bae Kim (hbkim@delta.ft.uam.es)
  17. Copying policy : GNU Public License
  18. "
  19.  
  20. #----------------------------------------------------------------
  21. # README
  22. #----------------------------------------------------------------
  23. set readme_tkscan "
  24.    TkScan version $c(version)
  25.    A tcl/tk GUI for command-line scanner driver
  26.    Copyright (C) 1997 Hang Bae Kim (hbkim@delta.ft.uam.es)
  27.  
  28.    This program is free software; you can redistribute it and/or
  29.    modify it under the terms of the GNU General Public License as
  30.    published by the Free Software Foundation; either version 2 of
  31.    the License, or (at your option) any later version.
  32.  
  33.    This program is distributed in the hope that it will be useful,
  34.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  35.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  36.    See the GNU General Public License for more details.
  37.  
  38.  TkScan is a tcl/tk GUI for command-line scanner driver.
  39.  I have written it for my own use with my Mustek 800IISP scanner.
  40.  But I put it in the public with the hope that it may be helpful to someone.
  41.  Remember that scanning itself is done by the scanner driver not by this
  42.  GUI.  Therefore you NEED the appropriate command-line scanner driver for
  43.  your scanner. TkScan just does the scanning area selection on a previewed
  44.  image, the choice of options, e.g. scanning mode, resolution and some
  45.  enhancements like gamma correction, running scanner driver and sending the
  46.  output where you want.  You can fit it to your scanner and driver without
  47.  much difficulty, by modifying `scanner_driver'.tcl referring your driver
  48.  manual.
  49.  
  50.  Currently it supports
  51.     * Epson SCSI scanner via `ep_scan'
  52.     * HP SCSI scanner via `hpscanpbm'
  53.     * Microtek SCSI scanner via `mtekscan'
  54.     * Mustek Flatbed scanner via `scanimage'(SANE) or `mscan'
  55.  
  56.     - I wrote `epson-ep_scan.tcl' `hp-hpscanpbm.tcl' `microtek-mtekscan.tcl'
  57.       just referring manuals, without testing.  They can be considered as
  58.       scratch.  So they may not work, or even may include simple typos.
  59.       I hope you can cope with this situation. If you write a correctly
  60.       working script, please send a copy to me.
  61.     - I give thanks to Boris Tobotras(tobotras@jet.msk.su) for sending
  62.       the patch for hpscanpbm.
  63.  
  64.  With TkScan you can
  65.     * preview an image to be scanned on a small canvas whose size and
  66.       mode you can select
  67.     * adjust scanning mode and resolutions and other options
  68.       supported by the scanner and driver with mouse clicks
  69.     * select the one or more scanning areas on a previewed image canvas
  70.       If you select several scanning areas, TkScan will scan them successively.
  71.       TkScan shows the expected screen pixel sizes and raw data sizes of the
  72.       images as well as its real size in several length units (mm,cm,pt,inch).
  73.     * make the output raw data directly go where you want:
  74.         - to image editor (XV, ImageMagic or GIMP),
  75.         - to file in the format you want,
  76.         - to printer or to ghostscript(ghostview or gv) in postscript format
  77.           with the size and position adjustment,
  78.         - to fax modem to be directly sent as a fax,
  79.         - to the ocr software to be processed by ocr
  80.           (_not_ implemented yet in this version).
  81.     * see the progress of scanning both in graphic and numeric percentage
  82.       and file size fraction.
  83.     * interrupt scanning with the Stop button.
  84.     * configure TkScan to fit it to your tastes.
  85.     
  86.  TkScan requires
  87.     * Scanner and command-line driver listed above, or you can add your own.
  88.     * Tcl/Tk, probably most versions will work.
  89.     * ImageMagic, to convert the scanned image to various formats
  90.     * XV, ImageMagic, or GIMP or all of them, for ImageEditor
  91.     * Ghostscript and ghostview(or gv), to view the postscript output
  92.     * Efax, to send the scanned image to a fax modem
  93.  
  94.     - I left the output to OCR blank, Because I could not find a good
  95.       OCR software for Linux.  Does anyone know about it?
  96.     - All the above binaries should lie in your PATH.
  97.  
  98.  How to use
  99.     See Guide in the Help menu.
  100.  
  101.  Bug or Comment to
  102.     Hang-Bae Kim, hbkim@delta.ft.uam.es
  103. "
  104.  
  105. #----------------------------------------------------------------
  106. # Usage of TkScan
  107. #----------------------------------------------------------------
  108. set usage_tkscan "
  109.  How to use TkScan version $c(version)
  110.  
  111.  Contents
  112.  
  113.     0. Command line option
  114.     1. Previewing
  115.     2. Selection of regions to be scanned
  116.     3. Selection of mode and resolution
  117.     4. Selection of output destination
  118.     5. Scanning
  119.     6. Configuration
  120.  
  121.  
  122.  Section 0. Command line option
  123.  
  124.    tkscan \[-geometry +x+y\] \[ImageEditor|File|Printer|Fax|OCR\]
  125.  
  126.  
  127.  Section 1. Preview
  128.  
  129.  * Click \[Preview\] button to initiate preview scanning.
  130.  * Preview scanning can be interrupted by clicking \[Stop\] button.
  131.  * The preview mode and resolution can be chosen in Preference of File menu.
  132.  
  133.  
  134.  Section 2. Selection of regions to be scanned
  135.  
  136.  * The selection of scanning regions on the preview image is done with
  137.    left mouse button. Press left button at one corner of the rectangle you
  138.    want to scan, move mouse while pressing it and release at the other corner.
  139.  * You can finetune the region using finetuning buttons around blue rectangle.
  140.  * The blue rectagle continuously shows a region to be scanned, while the
  141.    scanning region window diplays coordinates of upper-left and lower-right
  142.    coners, the width times height in the length unit chosen (Real Size) and
  143.    in screen pixel (Screen Size), and the file size of the image in raw
  144.    format (Data Size).  Screen Size and Data Size also vary as you change
  145.    scanning mode and resolution.
  146.  * The size of A4, Letter paper or others are preset in \[preset\] button.  You
  147.    can add your own regions in configuration file (See Configuration section).
  148.  * You can select several regions on the preview image canvas.
  149.    Set one blue rectangle and click the middle mouse button inside it (or
  150.    \[Regist\] button).  Blue rectangle becomes red and the number 1 appears
  151.    at the center.  Then make another blue rectangle and press the middle
  152.    button inside it.  Now the second red rectangle is registered.  Repeat
  153.    this as many times as you want.  Click of the right mouse button inside
  154.    the red rectangle will remove it.  Double click of the right button (or
  155.    click of the \[Clear\] button) deletes all rectangles.  TkScan will scan
  156.    red rectangles successively in order of their registration numbers.
  157.  
  158.  
  159.  Section 3. Selection of mode, resolution and options
  160.  
  161.  This is transparent: Use mode \[Mode\] menubutton and \[Resolution\] scale.
  162.  Screen Size and Data Size change accordingly as mode and resolution change.
  163.  * If you want to adjust other options, press \[Open Manager\] button.  Then
  164.    Option manager window appears and you can do it there.  Available options
  165.    depend on the scanning mode.
  166.  * Several frequently used mode are preset in Mode munu.  You can define your
  167.    own quick_mode in configuration file (See Configuration section.)
  168.  
  169.  
  170.  Section 4. Selection of output desination
  171.  
  172.  This is done by \[Output to\] menubutton.
  173.  
  174.  * Image Editor
  175.    - You can select image editor among XV, ImageMagic and GIMP in Preference.
  176.    - There is also \[SW\] checkbutton, which select that each scanned image
  177.      appears in separate image editor or all images in one image editor
  178.      when several red rectangles are scanned successively.
  179.  
  180.  * File
  181.    If you select this, File Manager Window appears.
  182.    - Select the output file format.
  183.    - You can specify a filename for scanned image in \[Filename\] entry.
  184.      If you use # in the filename, the last # is replaced with the retangle
  185.      number(0 for blue rectangle, the number at the center for red rectangles).
  186.      The default filename is scanout-#.surfix where appropriate surfix is
  187.      attached for the file format. You can change it in the configuration file.
  188.  
  189.  * Printer
  190.    If you select this, Print Manager Window appears.
  191.    - Select a printer.  `gv' is for sending output to ghostview(or gv).
  192.    - Use \[Zoom\] scale and \[Position\] menubutton to select the size and
  193.      position of printed image. Zoom scale is percentage of Real Size.
  194.    - \[Reprint\] button is for printing again the scanned image with changed
  195.      zoom and position.
  196.  
  197.  * Fax
  198.    If you select this, Fax Manager Window appears.
  199.    - With this, each scanned page is converted tiffg3 format using efix and
  200.      listed in Page List Box.
  201.    - In Page List Box, you can
  202.       + view each page converted to tiffg3 format by double click of
  203.         left mouse button,
  204.       + view whole pages by pressing \[View\] button,
  205.       + rearrange the order of pages using \[Up\] and \[Down\] button,
  206.       + remove a page from the list using \[Remove\] button,
  207.       + \[Attach\] button does not work yet.
  208.    - You should specify the fax number.  \[List\] calls Fax Number List Window,
  209.      in which you can maintain frequently used fax numbers.
  210.  
  211.  * OCR
  212.    - This is not implemented yet. I could not find a good OCR software running
  213.      under Linux. Please let me know if anyone knows or heard of it.
  214.  
  215.  
  216.  Section 5. Scanning
  217.  
  218.  This is done by pressing \[SCAN\] button. TkScan will scan the blue rectangle
  219.  region. If you registered red rectangles, then red rectangle regions are
  220.  scanned successively and the blue rectangle is ignored even when it exists.
  221.  As scanning is in progress, the progress report appears in the status bar.
  222.  If you want to interrupt in the middle of scanning, press \[Stop\] button.
  223.  It kill driver command and recover the state before scanning.
  224.  If it does not work for some reason, double click \[Stop\] button. This
  225.  surely stops scanning and recover TkScan for another scanning.
  226.  Note that while \[Stop\] button kills scanning command immediately,
  227.  it takes some time for scanner to respond.  Scanner is a slowly responding
  228.  peripharal.  I do not recommend frequent use of \[Stop\] button.
  229.  
  230.  
  231.  Section 6. Configuration
  232.  
  233.  If you select Preference in File menu, Preference Window appears.
  234.  * Specify your scanner device if your scanner driver does not find the
  235.    scanner device correctly without device option. Otherwise, to leave it
  236.    blank is OK.
  237.  * You can change the preview image mode and resolution to those you prefer.
  238.    Press \[Apply\] button after selection.
  239.  * Gamma correction can be done either by the driver itself or by the
  240.    external programs like xv or ImageMagic's display or convert if it is
  241.    not available in the driver. Choose what you prefer.
  242.  * TkScan makes ~/.tkscan directory to keep its configuration files and
  243.    scanned image files temporarily. You can delete those temporary files in
  244.    this directory when exit or right now to free your hard disk.
  245.  * If you select Save current config in File menu, the various configuration
  246.    settings are stored in the ~/.tkscan/init file.  You can modify this file
  247.    to fit your taste.  If you feel like doing more changes, observe the
  248.    `tkscan' script and copy necessary parts to ~/.tkscan/init file,
  249.    then modify them.
  250. "
  251.  
  252. #------------------------------------------------------------------------
  253. # MicroTek SCSI scanner -- mtekscan
  254. #------------------------------------------------------------------------
  255.  
  256. # Full scanning size. This should be in inches.
  257. set s(scanwidth)    8.5
  258. set s(scanheight)    11.6
  259.  
  260. # Minimum, maximum and step of scanning resolution in dpi
  261. set s(resolutionRange)    {1 600 1}
  262.  
  263. # Time(in miliseconds) for coming back from the opposite end 
  264. # after finishing full height scanning
  265. set s(scantime)        20000
  266.  
  267. # Command-line driver
  268. set s(command)    "mtekscan"
  269.  
  270. # Scanner device (leave empty for autodetection)
  271. set s(device)        ""
  272.  
  273. # Options other than for mode and resolution
  274. #     Label         Type  Variable      Values or Range  Default value
  275. set s(optionList) { 
  276.     { {Backtrack}      m  backtrack     {yes no}  yes }
  277.     { {Speed}          r  speed         {1 7 1}  1 }
  278.     { {Brightness}     r  brightness    {-100 100 1}  0 }
  279.     { {Exposure Time}  r  exposuretime  {-18 21 3}  0 }
  280.     { {Contrast}       r  contrast      {-42 49 1}  0 }
  281.     { {Halftoning}     r  halftoning    {0 11 1}  0 }
  282.     { {Shadow}         r  shadow        {0 255 1}  0 }
  283.     { {Midtone}        r  midtone       {0 255 1}  128 }
  284.     { {Highlight}      r  highlight     {0 255 1}  255 }
  285.     { {Gamma}          r  gamma         {0.2 5.0 0.1}  1.0 }
  286. }
  287. set s(modedepoptionList) { shadow midtone highlight halftoning gamma }
  288.  
  289. # Supported scanning modes
  290. #     Mode   Format  bpp  Mode-dependent options
  291. set s(modeList) {
  292.     { Lineart   pbm   1  {} }
  293.     { Halftone  pbm   1  {halftoning} }
  294.     { Gray      pgm   8  {shadow midtone highlight gamma} }
  295.     { Color     ppm  24  {shadow midtone highlight gamma} }
  296. }
  297.  
  298. # Gamma correction support
  299. # 0 : support by scanner driver
  300. # 1 : support by external (image editor, image converter) commands
  301. set s(gamma_support)    0
  302.  
  303. #------------------------------------------------------------------------
  304. # Procedure launching scanner driver
  305. #------------------------------------------------------------------------
  306.  
  307. proc run_scanner_driver { i file } { global s c
  308.     set command $s(command)
  309.     set file "-o $c(tkscandir)/$file.pnm"
  310.     foreach j {tx ty bx by} { set $j [pixelto inch [expr $s($j$i)-$s(o)]] }
  311.     set geometry "-f $tx $ty $bx $by"
  312.     switch $s(mode) {
  313.         Lineart        { set mode "-b" }
  314.         Halftone    { set mode "-a" }
  315.         Gray        { set mode "-g" }
  316.         Color        { set mode "-c" }
  317.     }
  318.     set resolution "-r $s(resolution)"
  319.     set option "-v $s(speed) -k $s(contrast) -d $s(brightness) \
  320.                 -e $s(exposuretime)"
  321.     if {$s(backtrack) == "no"} {append option " -B"}
  322.     foreach i $s($s(mode)option) { switch $i {
  323.       halftoning  {append option " -H $s(halftoning)"}
  324.       shadow      {append option " -s $s(shadow)"}
  325.       midtone     {append option " -m $s(midtone)"}
  326.       highlight   {append option " -l $s(highlight)"}
  327.       gamma       { if {$s(gamma_support)==0} {append option " -G $s(gamma)"}}
  328.     }}
  329.     set cmdline "$command $s(device) $mode $resolution $option $geometry $file"
  330.     exec sh -c "echo $cmdline" &
  331. }
  332.  
  333. #----------------------------------------------------------------
  334. # Miscellanous Configuration
  335. #----------------------------------------------------------------
  336.  
  337. # Period in miliseconds for checking scanning progress
  338. set s(loopperiod)    1000
  339.  
  340. # Preview and Scan mode
  341. set c(prefile)            preview
  342. set s(preresolutionRange)       {15 40 1}
  343. set s(premode)                  Gray
  344. set s(preresolution)            27
  345. set s(Defaultmode)        Color
  346. set s(Defaultresolution)    150
  347.  
  348. # Quick mode description: unspecified options are set to Default.
  349. set c(mode_quick_set) {
  350.     { Copy     { mode=Gray    resolution=150 } }
  351.     { Fax      { mode=Lineart resolution=200 } } 
  352.     { OCR      { mode=Lineart resolution=300 } }
  353.     { Default  {} }
  354. }
  355.  
  356. # Paper quick settings, length in inch.
  357. set c(size_quick_set) {
  358.     { Max     { 0.0  0.0    $s(scanwidth) $s(scanheight) } }
  359.     { A4      { 0.0  0.0    8.268  11.6  } }
  360.     { Letter  { 0.0  0.0    8.5    11.0  } }
  361.     { Photo   { 0.0  0.0    5.906  3.937 } }
  362. }
  363.  
  364. # Length units, their display formats and conversion factors
  365. set s(unitList) {
  366.     { mm    25.5  %0.0f }
  367.     { cm    2.54  %0.1f }
  368.     { inch   1.0  %0.2f }
  369.     { pt    72.0  %0.0f }
  370. }
  371.  
  372. # Define variables for later use
  373. foreach i $s(optionList) {
  374.     set variable [lindex $i 2]
  375.     set default  [lindex $i 4]
  376.     set s(Default$variable) $default
  377.     set s(pre$variable) $default
  378. }
  379. foreach i $s(modeList) { set modename [lindex $i 0]
  380.     set s([set modename]format) [lindex $i 1]
  381.     set s([set modename]dsizefactor) [lindex $i 2]
  382.     set s([set modename]option) [lindex $i 3]
  383. }
  384. foreach i $s(unitList) { set unitname [lindex $i 0]
  385.     set s(c$unitname) [lindex $i 1]
  386.     set s(f$unitname) [lindex $i 2]
  387. }
  388. foreach i $c(mode_quick_set) { set c(qmode[lindex $i 0]) [lindex $i 1] }
  389. foreach i $c(size_quick_set) { set c(qpaper[lindex $i 0]) [lindex $i 1] }
  390.  
  391. # Adopted scanning mode options in this program
  392. set s(settingList) "mode resolution"
  393. foreach i $s(optionList) {lappend s(settingList) [lindex $i 2]}
  394. foreach i $s(settingList) {set s($i) $s(Default$i)}
  395.  
  396. # Fonts
  397. # entry font
  398. set l(f1) -adobe-helvetica-bold-r-*--12-120-*-*-*-*-*-*
  399. # fixed font
  400. set l(f2) -bitstream-courier-bold-r-*--14-140-*-*-*-*-*-*
  401.  
  402. # Color
  403. # entry color
  404. set l(c1) blue
  405. # primary rectangle
  406. set l(c2) blue
  407. # registed rectangle
  408. set l(c3) red
  409. # currently processed rectangle
  410. set l(c5) blue
  411. # scanning progress bar
  412. set l(c6) blue
  413.  
  414. #----------------------------------------------------------------
  415. # User Configuration
  416. #----------------------------------------------------------------
  417.  
  418. # The directory where the configuration file and temporary files are kept
  419. set c(tkscandir) $env(HOME)/.tkscan
  420. if [file exists $c(tkscandir)] {
  421.     if [file isdirectory $c(tkscandir)] {
  422.     } else {
  423.         puts "tkscan: ~/.tkscan exists but not a directory"
  424.         exit
  425.     }
  426. } else {
  427.     puts "tkscan: No $c(tkscandir) directory, create it."
  428.     exec mkdir $c(tkscandir)
  429. }
  430. set c(scanout)        ""
  431. set c(userconf)        "$c(tkscandir)/init"
  432. set c(tmpdirclear)    1
  433.  
  434. # The following entries are saved in the user configuration file.
  435. set s(saveList) "device preresolutionRange premode preresolution pregamma unit"
  436. foreach i $s(settingList) {append s(saveList) " Default$i"}
  437. set c(saveList) "mode_quick_set size_quick_set tmpdirclear"
  438.  
  439. #----------------------------------------------------------------
  440. # Main Window
  441. #----------------------------------------------------------------
  442.  
  443. proc mainWindow {} { global s c w l
  444.  
  445.     # Menubar
  446.     #
  447.     frame .menu -bd 1 -relief flat
  448.     pack .menu -side top -fill x
  449.     mb .menu.f File .menu.f.m
  450.     mb .menu.m Mode .menu.m.m
  451.     mb .menu.h Help .menu.h.m
  452.     label .menu.l -text "TkScan v$c(version)" -width 15 -pady 0 \
  453.           -fg red -font -*-times-bold-r-*--14-140-*
  454.     pack .menu.f .menu.m .menu.l -side left
  455.     pack .menu.h -side right
  456.     menu .menu.f.m -tearoff false
  457.          .menu.f.m add command -label Preference -command preferenceWindow
  458.          .menu.f.m add command -label "Set current as Default" \
  459.                                -command "savecur Default"
  460.          .menu.f.m add command -label "Save current config" \
  461.                                -command "savesettings"
  462.          .menu.f.m add separator
  463.          .menu.f.m add command -label Quit -command do_exit
  464.     menu .menu.m.m -tearoff false
  465.     foreach i $c(mode_quick_set) {
  466.         set qmodename [lindex $i 0]
  467.         .menu.m.m add command -command "setquickmode $qmodename" \
  468.                               -label $qmodename
  469.     }
  470.     menu .menu.h.m -tearoff false
  471.          .menu.h.m add command -label About  -command aboutWindow
  472.          .menu.h.m add command -label Readme -command readmeWindow
  473.          .menu.h.m add command -label Guide  -command usageWindow
  474.  
  475.     # Separator - not indispensible, just for good looking.
  476.     canvas .sep1  -relief sunken -height 0 -borderwidth 1
  477.     pack .sep1 -side top -fill x
  478.  
  479.     # Left frame
  480.     #
  481.     frame .left -bd 5 -relief flat
  482.     pack .left -side left -anchor nw -fill y
  483.  
  484.     # Preview image canvas
  485.     set w(prev) .left.preview
  486.     canvas $w(prev) -relief sunken
  487.     pack $w(prev) -side top
  488.     bind $w(prev) <ButtonPress-1>    "settop        %x %y"
  489.     bind $w(prev) <B1-Motion>        "setbottom    %x %y"
  490.     bind $w(prev) <ButtonPress-2>    "registrect    %x %y"
  491.     bind $w(prev) <ButtonPress-3>    "deleterect    %x %y"
  492.     bind $w(prev) <Double-Button-3>    "deleteallrect"
  493.  
  494.     # Right frame
  495.     #
  496.     frame .right -bd 5 -relief flat
  497.     pack .right -side left -expand yes -fill both
  498.  
  499.     # OUTPUT
  500.     set w(ou) .right.output
  501.     set w(outputto) $w(ou).u.m
  502.     frame $w(ou) -bd 1 -relief groove
  503.     frame $w(ou).u
  504.     pack $w(ou).u -side top -fill x
  505.     rl $w(ou).u.l "Output to"
  506.     menubutton $w(outputto) -menu $w(ou).u.m.m \
  507.                -anchor w -width 18 -padx 6 -pady 2 -relief ridge -fg $l(c1)
  508.     pack $w(ou).u.l $w(ou).u.m -side left -fill x
  509.     menu $w(ou).u.m.m -tearoff false
  510.     foreach i $c(outputtoList) { set label [lindex $i 0]
  511.         $w(ou).u.m.m add command -label $label -command "setoutputto $label"
  512.     }
  513.  
  514.     # Scanning mode selection
  515.     set w(mo) .right.mode
  516.     frame $w(mo) -bd 1 -relief groove
  517.     # MODE
  518.     frame $w(mo).m
  519.     pack $w(mo).m -side top -anchor nw -fill x
  520.     rl $w(mo).m.label "Mode"
  521.     menubutton $w(mo).m.mode -menu $w(mo).m.mode.m \
  522.                -anchor w -width 18 -padx 6 -pady 2 -relief ridge -fg $l(c1)
  523.     pack $w(mo).m.label $w(mo).m.mode -side left
  524.     menu $w(mo).m.mode.m -tearoff false
  525.     foreach i $s(modeList) { set modename [lindex $i 0]
  526.         $w(mo).m.mode.m add command -label $modename \
  527.                                     -command "setmode $modename"
  528.     }
  529.     # RESOLUTION
  530.     frame $w(mo).r
  531.     pack $w(mo).r -side top -anchor nw
  532.     rl $w(mo).r.label "Resolution"
  533.     entry $w(mo).r.entry -textvariable s(resolution) \
  534.           -justify right -relief sunken -width 4 -font $l(f1) -fg $l(c1)
  535.     scale $w(mo).r.scale -variable s(resolution) -command setresolution \
  536.           -from [lindex $s(resolutionRange) 0] \
  537.           -to [lindex $s(resolutionRange) 1] \
  538.           -resolution [lindex $s(resolutionRange) 2] \
  539.           -length 100 -orient horizontal -showvalue false
  540.     pack $w(mo).r.label $w(mo).r.entry $w(mo).r.scale -side left
  541.     # OPTIONS
  542.     frame $w(mo).e
  543.     pack $w(mo).e -side top -anchor nw
  544.     rl $w(mo).e.label "Options"
  545.     button $w(mo).e.button -text "Open Manager >>" \
  546.            -command optionWindow \
  547.            -anchor e -width 19 -relief ridge -padx 0 -pady 0
  548.     set w(optionbutton) $w(mo).e.button
  549.     pack $w(mo).e.label $w(mo).e.button -side left
  550.  
  551.     # SCANNING GEOMETRY DISPLAY
  552.     set w(ge) .right.geometry
  553.     frame $w(ge) -bd 1 -relief groove
  554.     canvas $w(ge).xy -width 210 -height 80 -bd 1 -relief flat
  555.     pack $w(ge).xy -fill x
  556.     set w(ft) $w(ge).xy
  557.     set finetune_buttons {
  558.         { tx- {  8 17 } {  8 33 } {  0 25 } }
  559.         { tx+ { 13 17 } { 13 33 } { 21 25 } }
  560.         { bx- { 38 17 } { 38 33 } { 30 25 } }
  561.         { bx+ { 43 17 } { 43 33 } { 51 25 } }
  562.         { ty- { 17  8 } { 33  8 } { 25  0 } }
  563.         { ty+ { 17 13 } { 33 13 } { 25 21 } }
  564.         { by- { 17 38 } { 33 38 } { 25 30 } }
  565.         { by+ { 17 43 } { 33 43 } { 25 51 } }
  566.     }
  567.     set xs 86
  568.     set ys 21
  569.     $w(ft) create rectangle [expr 10+$xs] [expr 10+$ys] \
  570.                             [expr 40+$xs] [expr 40+$ys] -outline blue
  571.     foreach i $finetune_buttons {
  572.         set btag [lindex $i 0]
  573.         for {set j 1} {$j<=3} {incr j} {
  574.             set x$j [expr [lindex [lindex $i $j] 0] +$xs]
  575.             set y$j [expr [lindex [lindex $i $j] 1] +$ys]
  576.         }
  577.         $w(ft) create polygon $x1 $y1 $x2 $y2 $x3 $y3 -fill black -tag $btag
  578.         $w(ft) bind $btag <Any-Enter> "$w(ft) itemconfig current -fill red"
  579.         $w(ft) bind $btag <Any-Leave> "$w(ft) itemconfig current -fill black"
  580.         $w(ft) bind $btag <ButtonPress> "set s(xx) 0; finetune $btag"
  581.         $w(ft) bind $btag <ButtonRelease> "set s(xx) 1"
  582.     }
  583.     # Coordinates
  584.     $w(ft) create text [expr 5+$xs] [expr 15+$ys] -tag ul -anchor se \
  585.                        -fill $l(c1) -font $l(f1)
  586.     $w(ft) create text [expr 45+$xs] [expr 35+$ys] -tag lr -anchor nw \
  587.                        -fill $l(c1) -font $l(f1)
  588.     # Label and Buttons
  589.     rl $w(ft).l "Geometry"
  590.     label  $w(ft).u -text "Length Unit"
  591.     menubutton $w(ft).m -text $s(unit) -menu $w(ft).m.m \
  592.                         -width 4 -pady 0 -relief ridge -fg $l(c1)
  593.     menu $w(ft).m.m -tearoff false
  594.     foreach i $s(unitList) { set label [lindex $i 0]
  595.         $w(ft).m.m add command -label $label -command \
  596.                  "setunit $label ; $w(ft).m configure -text $label"
  597.     }
  598.     menubutton $w(ft).p -text "Preset" -menu $w(ft).p.m \
  599.                         -width 6 -pady 0 -relief ridge
  600.     menu $w(ft).p.m -tearoff false
  601.     foreach i $c(size_quick_set) {
  602.         set qpapername [lindex $i 0]
  603.         $w(ft).p.m add command -command "setquickpaper $qpapername" \
  604.                               -label $qpapername
  605.     }
  606.     button $w(ft).r -text Regist -command {registrect $s(tx0) $s(ty0)} \
  607.                     -padx 0 -pady 0 -relief ridge
  608.     button $w(ft).d -text Delete -command {deleterect $s(tx0) $s(ty0)} \
  609.                     -padx 0 -pady 0 -relief ridge
  610.     button $w(ft).c -text Clear  -command deleteallrect \
  611.                     -padx 0 -pady 0  -relief ridge
  612.     $w(ft) create window   0   0 -window $w(ft).l -anchor nw
  613.     $w(ft) create window 102   0 -window $w(ft).u -anchor nw
  614.     $w(ft) create window 177   0 -window $w(ft).m -anchor nw
  615.     $w(ft) create window 163  22 -window $w(ft).p -anchor nw
  616.     $w(ft) create window   0  39 -window $w(ft).r -anchor nw
  617.     $w(ft) create window   0  61 -window $w(ft).d -anchor nw
  618.     $w(ft) create window  46  61 -window $w(ft).c -anchor nw
  619.  
  620.     # SIZE : Real, Screen, Data
  621.     sizeline $w(ge).rs "Real Size" "mm^2"
  622.     sizeline $w(ge).ss "Screen Size" "pixel^2"
  623.     sizeline $w(ge).ds "Data Size" "KB"
  624.  
  625.     # BUTTONS
  626.     set w(bt) .right.buttons
  627.     frame $w(bt) -bd 1 -relief flat
  628.     button $w(bt).p -text Preview -command "Preview" -width 5 -pady 4
  629.     button $w(bt).s -text SCAN -command {Scan [timetagscanout]} \
  630.                     -width 10 -pady 4
  631.     button $w(bt).q -text Stop -command "set s(stop) 1" \
  632.                     -width 3 -pady 4 -state disabled
  633.     bind $w(bt).q <Double-Button-1> {
  634.         set s(pid) [getpid $s(command)]
  635.         if {"$s(pid)" != ""} { foreach i $s(pid) { exec kill -9 $i } }
  636.         set s(stop) 0
  637.         set s(runscan) 0
  638.         $w(bt).p configure -state normal
  639.         $w(bt).s configure -state normal
  640.         $w(bt).q configure -state disabled
  641.     }
  642.     pack $w(bt).p $w(bt).s $w(bt).q -side left -expand yes -fill x
  643.  
  644.     # MESSAGE LINE
  645.     # Scanning progress: percentage in  bar and number
  646.     set w(st) .right.status
  647.     set w(stat_text) $w(st).text
  648.     set w(stat_prog) $w(st).prog
  649.     set w(prog_bar) $w(stat_prog).bar
  650.     set w(prog_perc) $w(stat_prog).percent
  651.     set s(prog_bar_wd) 173
  652.     frame $w(st) -bd 1 -relief groove
  653.     pack $w(st) -side bottom -fill x
  654.     label $w(stat_text) -anchor w -relief flat -font $l(f1)
  655.     frame $w(stat_prog)
  656.     pack $w(stat_text) $w(stat_prog) -side top -fill x
  657.     canvas $w(prog_bar) -width $s(prog_bar_wd) -height 15 -bd 1 -relief ridge
  658.     label $w(prog_perc) -width 5 -padx 1 -pady 0 -anchor e -bd 1 -relief ridge
  659.     pack $w(prog_bar) $w(prog_perc) -side left
  660.     set s(sg) [$w(prog_bar) create rectangle 0 0 0 18 -fill $l(c6)]
  661.  
  662.     pack $w(ou) $w(mo) $w(ge) $w(bt) -side top -expand yes -fill x
  663.     pack $w(st) -side bottom -expand yes -fill x
  664.  
  665. }
  666.  
  667. #-----------------------------------------------------------------
  668. # Preference Window
  669. #-----------------------------------------------------------------
  670.  
  671. proc preferenceWindow {} { global s c w l
  672.     if [winfo exists .preference] { return }
  673.     toplevel .preference
  674.     wm title .preference "TkScan: Preference"
  675.  
  676.     # Driver and Device
  677.     set pd .preference.device
  678.     frame $pd -bd 1 -relief groove
  679.     frame $pd.u
  680.     frame $pd.d
  681.     pack $pd.u $pd.d -side top -fill x
  682.     label $pd.u.l -text Command -width 15 -anchor e
  683.     entry $pd.u.d -textvariable s(command) \
  684.                      -width 20 -font $l(f1) -fg $l(c1) -relief sunken
  685.     pack $pd.u.l $pd.u.d -side left
  686.     label $pd.d.l -text Device -width 15 -anchor e
  687.     entry $pd.d.d -textvariable s(device) \
  688.                      -width 20 -font $l(f1) -fg $l(c1) -relief sunken
  689.     pack $pd.d.l $pd.d.d -side left
  690.  
  691.     # Preview
  692.     set pp .preference.preview
  693.     frame $pp -bd 1 -relief groove
  694.     frame $pp.m
  695.     pack $pp.m -side top -fill x
  696.     label $pp.m.p -text "Preview Mode" -width 15 -anchor e
  697.     menubutton $pp.m.m -menu $pp.m.m.m -width 10 -relief ridge -fg $l(c1)
  698.     set w(premodebutton) $pp.m.m
  699.     pack $pp.m.p $pp.m.m -side left
  700.     menu $pp.m.m.m -tearoff false
  701.     foreach i $s(modeList) { set modename [lindex $i 0]
  702.         $pp.m.m.m add command -label $modename \
  703.                               -command "setpremode $modename"
  704.     }
  705.         $pp.m.m.m add command -label Current \
  706.                               -command "setpremode Current"
  707.     frame $pp.r
  708.     pack $pp.r -side top -fill x
  709.     label $pp.r.l -text "Resolution" -width 15 -padx 0 -anchor e
  710.     set s(prepreresolution) $s(preresolution)
  711.     entryscale $pp.r s(prepreresolution) {} $s(preresolutionRange) 60
  712.     button $pp.r.b -text Apply -width 5 -padx 0 \
  713.               -command {setpreresolution $s(prepreresolution)}
  714.     pack $pp.r.l $pp.r.e $pp.r.s $pp.r.b -side left
  715.     setpremode $s(premode)
  716.  
  717.     # Gamma support
  718.     set pg .preference.gamma
  719.     frame $pg -bd 1 -relief groove
  720.     label $pg.l -text "Gamma Support" -width 15 -anchor e
  721.     radiobutton $pg.1 -text Driver -variable s(gamma_support) -value 0
  722.     radiobutton $pg.2 -text External -variable s(gamma_support) -value 1
  723.     pack $pg.l $pg.1 $pg.2 -side left
  724.  
  725.     # Image Editor
  726.     set ie .preference.ie
  727.     frame $ie -bd 1 -relief groove
  728.     label $ie.l -text "Image Editor" -width 15 -anchor e
  729.     menubutton $ie.mb -menu $ie.mb.m -text $c(ImageEditor) \
  730.                       -width 12 -relief ridge -fg $l(c1)
  731.     checkbutton $ie.cb -text SW -variable c(ImageEditorWinmode)
  732.     pack $ie.l $ie.mb $ie.cb -side left
  733.     menu $ie.mb.m -tearoff false
  734.     foreach i $c(ImageEditorList) { set iename [lindex $i 0]
  735.         $ie.mb.m add command -label $iename -command "
  736.             $ie.mb configure -text $iename
  737.             set c(ImageEditor) $iename
  738.         "
  739.     }
  740.  
  741.     # Image and Fax viewer
  742.     set pv .preference.viewer
  743.     frame $pv -bd 1 -relief groove
  744.     frame $pv.1
  745.     frame $pv.2
  746.     pack  $pv.1 $pv.2 -side top
  747.     label $pv.1.l -text "Image Viewer" -width 15 -anchor e
  748.     entry $pv.1.e -textvariable file(viewer) -width 20 -fg $l(c1) -font $l(f1)
  749.     pack  $pv.1.l $pv.1.e -side left
  750.     label $pv.2.l -text "Fax Viewer" -width 15 -anchor e
  751.     entry $pv.2.e -textvariable fax(viewer)  -width 20 -fg $l(c1) -font $l(f1)
  752.     pack  $pv.2.l $pv.2.e -side left
  753.  
  754.     # Printer paper
  755.     set pa .preference.paper
  756.     frame $pa -bd 1 -relief groove
  757.     label $pa.l -text "Printer Paper" -width 15 -anchor e
  758.     radiobutton $pa.1 -text A4 -variable pr(paper) -value A4
  759.     radiobutton $pa.2 -text Letter -variable pr(paper) -value Letter
  760.     pack $pa.l $pa.1 $pa.2 -side left
  761.  
  762.     # Temporary directory
  763.     set pt .preference.tmpdir
  764.     frame $pt -bd 1 -relief groove
  765.     frame $pt.u
  766.     frame $pt.d
  767.     pack $pt.u $pt.d -side top -fill x
  768.     label $pt.u.1 -text "TMP Directory" -width 15 -anchor e
  769.     checkbutton $pt.u.2 -text "Clear when Exit" -variable c(tmpdirclear)
  770.     pack $pt.u.1 $pt.u.2 -side left -fill x
  771.     label $pt.d.1 -text "" -width 15 -anchor e
  772.     button $pt.d.2 -text "Clear Now" -width 12 \
  773.            -command clear_tkscandir
  774.     pack $pt.d.1 $pt.d.2 -side left -fill x
  775.  
  776.     # Packing
  777.     pack $pd $pp $pg $ie $pv $pa $pt -side top -fill x
  778.  
  779.     # Buttons
  780.     set pb .preference.button
  781.     frame $pb
  782.     pack $pb -side bottom -expand yes -fill x
  783.     button $pb.h -text Done -pady 0 -command { destroy .preference }
  784.     pack $pb.h -side left -expand yes -fill x
  785. }
  786.  
  787. #--------------------------------------------------------------------
  788. # optionWindow
  789. #--------------------------------------------------------------------
  790.  
  791. proc optionWindow {} { global s w l
  792.     if [winfo exists .option] {
  793.         $w(optionbutton) configure -text "Open Manager >>"
  794.         destroy .option
  795.         return
  796.     }
  797.     $w(optionbutton) configure -text "Close Manager <<"
  798.     frame .option -bd 5 -relief flat
  799.     pack  .option -side left -fill both
  800.  
  801.     label .option.ti -text "TkScan Option Manager" \
  802.                      -width 24 -pady 4 -relief ridge
  803.     canvas .option.sep -width 0 -height 5 -relief flat
  804.     pack  .option.ti .option.sep -side top
  805.  
  806.     foreach i $s(optionList) {
  807.         set Label       [lindex $i 0]
  808.         set Type        [lindex $i 1]
  809.         set Variable    [lindex $i 2]
  810.         set Values      [lindex $i 3]
  811.         set wn .option.$Variable
  812.         frame $wn
  813.         pack  $wn -side top -fill x
  814.         label $wn.l -text $Label -width 12 -anchor e
  815.         switch $Type {
  816.             s {}
  817.             m {
  818.                 menubutton $wn.mb -menu $wn.mb.m -text $s($Variable) \
  819.                   -anchor w -width 13 -padx 10 -pady 2 -relief ridge -fg $l(c1)
  820.                 menu $wn.mb.m -tearoff false
  821.                 pack $wn.l $wn.mb -side left
  822.                 foreach i $Values {
  823.                     $wn.mb.m add command -label $i -command \
  824.                              "set s($Variable) $i ; $wn.mb configure -text $i"
  825.                 }
  826.             }
  827.             r {
  828.                 entryscale $wn s($Variable) {} $Values 72
  829.                 pack $wn.l $wn.e $wn.s -side left
  830.             }
  831.         }
  832.     }
  833.     option_select
  834. }
  835.  
  836. #-------------------------------------------------------------------------
  837. # Windows for Help menu
  838. #-------------------------------------------------------------------------
  839.  
  840. proc aboutWindow {} { global about_tkscan
  841.     if [winfo exists .about] return
  842.     toplevel .about
  843.     wm title .about "TkScan: About"
  844.     label .about.l -text $about_tkscan
  845.     button .about.b -width 8 -text OK -command "destroy .about"
  846.     pack .about.l .about.b -side top
  847. }
  848.  
  849. proc readmeWindow {} {global readme_tkscan l
  850.     if [winfo exists .readme] return
  851.     toplevel .readme
  852.     wm title .readme "TkScan: README"
  853.     frame .readme.b
  854.     pack .readme.b -side top -fill x
  855.     label .readme.b.1 -text "TkScan README" -width 15
  856.     button .readme.b.2 -text Close -command {destroy .readme}
  857.     pack .readme.b.1 .readme.b.2 -side left
  858.     frame .readme.u
  859.     pack .readme.u -side top -fill x
  860.     text .readme.u.t -width 68 -height 20 -font $l(f1) \
  861.                      -yscrollcommand ".readme.u.s set"
  862.     pack .readme.u.t -side left
  863.     scrollbar .readme.u.s -command ".readme.u.t yview" -orient vertical
  864.     pack .readme.u.s -side right -fill y
  865.     .readme.u.t insert end $readme_tkscan
  866. }
  867.  
  868. proc usageWindow {} {global usage_tkscan l
  869.     if [winfo exists .usage] return
  870.     toplevel .usage
  871.     wm title .usage "TkScan: Guide"
  872.     frame .usage.b
  873.     pack .usage.b -side top -fill x
  874.     label .usage.b.1 -text "TkScan Guide" -width 15
  875.     button .usage.b.2 -text Close -command {destroy .usage}
  876.     pack .usage.b.1 .usage.b.2 -side left
  877.     frame .usage.u
  878.     pack .usage.u -side top -fill x
  879.     text .usage.u.t -width 68 -height 20 -font $l(f1) \
  880.          -yscrollcommand ".usage.u.s set"
  881.     pack .usage.u.t -side left
  882.     scrollbar .usage.u.s -command ".usage.u.t yview" -orient vertical
  883.     pack .usage.u.s -side right -fill y
  884.     .usage.u.t insert end $usage_tkscan
  885. }
  886.  
  887. #----------------------------------------------------------------
  888. # Procedures for configurations
  889. #----------------------------------------------------------------
  890.  
  891. proc savesettings {} { global s c
  892.     set file [open "$c(userconf)" w]
  893.     puts $file "# tkscan user configuration
  894. # If you feel like doing more changes, observe the `tkscan' script and
  895. # copy necessary parts here, then change them.\n"
  896.     foreach i $s(saveList) { puts $file "set s($i)\t\"$s($i)\"" }
  897.     foreach i $c(saveList) { puts $file "set c($i)\t\"$c($i)\"" }
  898.     puts $file "\n# end of tkscan user configuration"
  899.     close $file
  900. }
  901.  
  902. proc setcur { type } { global s w
  903.     foreach i $s(settingList) {set s($i) $s($type$i)}
  904.     setmode $s(mode)
  905. }
  906.  
  907. proc savecur { type } { global s
  908.     foreach i $s(settingList) {set s($type$i) $s($i)}
  909. }
  910.  
  911. proc setmode { mode } { global s c w
  912.     set s(mode) $mode
  913.     if $s(premodecurrent) { set s(premode) $mode }
  914.     $w(mo).m.mode configure -text $mode
  915.     if [winfo exists .option] { option_select }
  916.     showsize 0
  917. }
  918.  
  919. proc option_select {} { global s
  920.     foreach i $s(modedepoptionList) { .option.$i.l configure -fg gray }
  921.     foreach i $s($s(mode)option) { .option.$i.l configure -fg black }
  922. }
  923.  
  924. proc setquickmode { mode } { global s c
  925.     setcur Default
  926.     foreach k $c(qmode$mode) {
  927.         set l [string first = $k]
  928.         set arg [string range $k 0 [expr [string first = $k]-1]]
  929.         set val [string range $k [expr [string first = $k]+1] end]
  930.         set s($arg) $val
  931.     }
  932. #   if { [set i $c(qmode$mode\outputto)] != "" } { setoutputto $i }
  933.     setmode $s(mode)
  934. }
  935.  
  936. proc setquickpaper { paper } { global s c
  937.     for {set j 0} {$j<4} {incr j} { set z$j [format "%0.0f" \
  938.         [expr [lindex $c(qpaper$paper) $j]*$s(preresolution)+$s(o)]] }
  939.     settop $z0 $z1 ; setbottom $z2 $z3
  940. }
  941.  
  942. proc setpremode { mode } { global s w
  943.     $w(premodebutton) configure -text $mode
  944.     if { $mode == "Current" } {
  945.         set s(premodecurrent) 1
  946.         set s(premode) $s(mode)
  947.     } else {
  948.         set s(premodecurrent) 0
  949.         set s(premode) $mode
  950.     }
  951. }
  952.  
  953. proc setpreresolution { resolution } { global s w
  954.     set s(preresolution) $resolution
  955.     previewcanvas
  956.     deleteallrect
  957.     image create photo preview -data {}
  958. }
  959.  
  960. proc previewcanvas {} { global s w
  961.     set s(o) 6
  962.     set s(prebd) 2
  963.     set s(scanpwidth) [format "%0.0f" [expr $s(scanwidth) *$s(preresolution)]]
  964.     set s(scanpheight) [format "%0.0f" [expr $s(scanheight)*$s(preresolution)]]
  965.     set s(maxpwidth) [expr $s(scanpwidth) +$s(o)]
  966.     set s(maxpheight) [expr $s(scanpheight)+$s(o)]
  967.     set s(prewidth) [expr $s(scanpwidth) +2*($s(o)-$s(prebd)-1)]
  968.     set s(preheight) [expr $s(scanpheight)+2*($s(o)-$s(prebd)-1)]
  969.     $w(prev) configure -width $s(prewidth) -height $s(preheight) -bd $s(prebd)
  970. }
  971.  
  972. proc setresolution { resolution } { global s
  973.     set s(resolution) $resolution
  974.     showsize 0
  975. }
  976.  
  977. proc setunit { unit } { global s w
  978.     set s(unit) $unit
  979.     $w(ge).rs.unit configure -text "$unit^2"
  980.     showsize 0
  981. }
  982.  
  983. proc showsize { i } { global s w
  984.     set txd [format "$s(f$s(unit))" [pixelto $s(unit) [expr $s(tx$i)-$s(o)]]]
  985.     set tyd [format "$s(f$s(unit))" [pixelto $s(unit) [expr $s(ty$i)-$s(o)]]]
  986.     set bxd [format "$s(f$s(unit))" [pixelto $s(unit) [expr $s(bx$i)-$s(o)]]]
  987.     set byd [format "$s(f$s(unit))" [pixelto $s(unit) [expr $s(by$i)-$s(o)]]]
  988.     set wd [pixelto $s(unit) [expr $s(bx$i)-$s(tx$i)]]
  989.     set ht [pixelto $s(unit) [expr $s(by$i)-$s(ty$i)]]
  990.     set s(sizeReal) [format "$s(f$s(unit)) x $s(f$s(unit))" $wd $ht]
  991.     set pwd [expr [pixelto inch [expr $s(bx$i)-$s(tx$i)]] * $s(resolution).0]
  992.     set pht [expr [pixelto inch [expr $s(by$i)-$s(ty$i)]] * $s(resolution).0]
  993.     set dsizefactor $s($s(mode)dsizefactor)
  994.     set dsize [expr $pwd * $pht * $dsizefactor / 8192.0]
  995.     set s(sizeScreen)    [format "%0.0f x %0.0f" $pwd $pht]
  996.     set s(sizeData)    [format "%0.1f" $dsize]
  997.     $w(ft) itemconfigure ul -text "($txd, $tyd)"
  998.     $w(ft) itemconfigure lr -text "($bxd, $byd)"
  999.     $w(ge).rs.size configure -text "$s(sizeReal)"
  1000.     $w(ge).ss.size configure -text "$s(sizeScreen)"
  1001.     $w(ge).ds.size configure -text "$s(sizeData)"
  1002. }
  1003.  
  1004. #----------------------------------------------------------------
  1005. # Procedures for Scanning Area Selection
  1006. #----------------------------------------------------------------
  1007.  
  1008. proc settop { xp yp } { global s w l
  1009.     if { $xp < $s(o) } { set xp $s(o) }
  1010.     if { $yp < $s(o) } { set yp $s(o) }
  1011.     if { $xp > $s(maxpwidth) } { set xp $s(maxpwidth) }
  1012.     if { $yp > $s(maxpheight) } { set yp $s(maxpheight) }
  1013.     set s(tx0) $xp
  1014.     set s(ty0) $yp
  1015.     set s(bx0) $s(tx0)
  1016.     set s(by0) $s(ty0)
  1017.     $w(prev) delete $s(rect0)
  1018.     set s(rect0) [$w(prev) create rectangle $s(tx0) $s(ty0) $s(bx0) $s(by0) \
  1019.                   -width 1 -outline $l(c2)]
  1020.     showsize 0
  1021. }
  1022.  
  1023. proc setbottom { xp yp } { global s w
  1024.     if { $xp < $s(o) } { set xp $s(o) }
  1025.     if { $yp < $s(o) } { set yp $s(o) }
  1026.     if { $xp > $s(maxpwidth) } { set xp $s(maxpwidth) }
  1027.     if { $yp > $s(maxpheight) } { set yp $s(maxpheight) }
  1028.     if { $xp > $s(tx0) } { set s(bx0) $xp } else { set s(tx0) $xp }
  1029.     if { $yp > $s(ty0) } { set s(by0) $yp } else { set s(ty0) $yp }
  1030.     $w(prev) coords $s(rect0) $s(tx0) $s(ty0) $s(bx0) $s(by0)
  1031.     showsize 0
  1032. }
  1033.  
  1034. proc finetune { arg } { global s w
  1035.     if $s(xx) { return }
  1036.     switch $arg {
  1037.         tx- {if {$s(tx0) <= $s(o)} {return}}
  1038.         tx+ {if {$s(tx0) >= $s(bx0)} {return}}
  1039.         ty- {if {$s(ty0) <= $s(o)} {return}}
  1040.         ty+ {if {$s(ty0) >= $s(by0)} {return}}
  1041.         bx- {if {$s(bx0) <= $s(tx0)} {return}}
  1042.         bx+ {if {$s(bx0) >= $s(maxpwidth)} {return}}
  1043.         by- {if {$s(by0) <= $s(ty0)} {return}}
  1044.         by+ {if {$s(by0) >= $s(maxpheight)} {return}}
  1045.     }
  1046.     incr s([string range $arg 0 1]0) [string index $arg 2]1
  1047.     $w(prev) coords $s(rect0) $s(tx0) $s(ty0) $s(bx0) $s(by0)
  1048.     showsize 0
  1049.     after 200 finetune $arg
  1050. }
  1051.  
  1052. proc registrect { xp yp } { global s w l
  1053.     if [isinside $xp $yp $s(tx0) $s(ty0) $s(bx0) $s(by0)] {
  1054.         incr s(nrect) 1
  1055.         set s(tx$s(nrect)) $s(tx0)
  1056.         set s(ty$s(nrect)) $s(ty0)
  1057.         set s(bx$s(nrect)) $s(bx0)
  1058.         set s(by$s(nrect)) $s(by0)
  1059.         $w(prev) coords $s(rect0) 0 0 0 0
  1060.         set s(rect$s(nrect)) [$w(prev) create rectangle \
  1061.             $s(tx$s(nrect)) $s(ty$s(nrect)) $s(bx$s(nrect)) $s(by$s(nrect)) \
  1062.             -width 1 -outline $l(c3)]
  1063.         set s(num$s(nrect)) [$w(prev) create text \
  1064.                     [expr ( $s(tx$s(nrect)) + $s(bx$s(nrect))) / 2] \
  1065.                     [expr ( $s(ty$s(nrect)) + $s(by$s(nrect))) / 2] \
  1066.                     -text $s(nrect) -fill $l(c3)]
  1067.         stat_text "Registered Regions: $s(nrect)"
  1068.     }
  1069.  
  1070. }
  1071.  
  1072. proc deleterect { xp yp } { global s w l
  1073.     for {set i 1} {$i <= $s(nrect)} {incr i} {
  1074.         if [isinside $xp $yp $s(tx$i) $s(ty$i) $s(bx$i) $s(by$i)] {
  1075.             $w(prev) delete $s(rect$i)
  1076.             $w(prev) delete $s(num$i)
  1077.             set j $i
  1078.             while { $j < $s(nrect) } {
  1079.                 set k [expr $j + 1]
  1080.                 set s(tx$j) $s(tx$k)
  1081.                 set s(ty$j) $s(ty$k)
  1082.                 set s(bx$j) $s(bx$k)
  1083.                 set s(by$j) $s(by$k)
  1084.                 set s(rect$j) $s(rect$k)
  1085.                 $w(prev) delete $s(num$k)
  1086.                 set s(num$j) [$w(prev) create text \
  1087.                     [expr ( $s(tx$j) + $s(bx$j)) / 2] \
  1088.                     [expr ( $s(ty$j) + $s(by$j)) / 2] \
  1089.                     -text $j -fill $l(c3)]
  1090.                 incr j 1
  1091.             }
  1092.             incr s(nrect) -1
  1093.             stat_text "Registered Regions: $s(nrect)"
  1094.             break
  1095.         }
  1096.     }
  1097. }
  1098.  
  1099. proc deleteallrect {} { global s w l
  1100.     for {set i 1} {$i <= $s(nrect)} {incr i} {
  1101.         $w(prev) delete $s(rect$i)
  1102.         $w(prev) delete $s(num$i)
  1103.     }
  1104.     set s(nrect) 0
  1105.     $w(prev) coords $s(rect0) 0 0 0 0
  1106.     stat_text "Registered Regions: $s(nrect)"
  1107. }
  1108.  
  1109. #----------------------------------------------------------------
  1110. # (Combined) Widgets
  1111. #----------------------------------------------------------------
  1112.  
  1113. proc mb { wn text menu } { menubutton $wn -text $text -menu $menu \
  1114.                            -underline 0 -width 8 -relief flat }
  1115.  
  1116. proc rl { wn text } { label $wn -text "$text" -width 10 -anchor e }
  1117.  
  1118. proc entryscale { wn var command range length } { global l
  1119.     entry $wn.e -textvariable $var \
  1120.           -justify right -relief sunken -width 4 -font $l(f1) -fg $l(c1)
  1121.     scale $wn.s -variable $var -command $command \
  1122.           -from       [lindex $range 0] \
  1123.           -to         [lindex $range 1] \
  1124.           -resolution [lindex $range 2] \
  1125.           -length $length -orient horizontal -showvalue false
  1126. }
  1127.  
  1128. proc sizeline { wn label unit } { global w l
  1129.     frame $wn
  1130.     pack  $wn -side top -anchor nw
  1131.     label $wn.label -text $label -width 10 -anchor e
  1132.     label $wn.size -anchor e -relief flat -width 12 -font $l(f1) -fg $l(c1)
  1133.     label $wn.unit -text $unit -anchor w -width 6 -padx 4 -relief flat
  1134.     pack  $wn.label $wn.size $wn.unit -side left
  1135. }
  1136.  
  1137. #----------------------------------------------------------------
  1138. # Miscellaneous procedures
  1139. #----------------------------------------------------------------
  1140.  
  1141. proc do_exit {} { global c
  1142.     if $c(tmpdirclear) { clear_tkscandir }
  1143.     exit
  1144. }
  1145.  
  1146. proc clear_tkscandir {} { global c
  1147.     exec sh -c "rm -f $c(tkscandir)/$c(prefile).* $c(tkscandir)/$c(scanout)*"
  1148. }
  1149.  
  1150. proc stat_text { message } { global w
  1151.     $w(stat_text) configure -text "$message"
  1152. }
  1153.  
  1154. proc timetagscanout {} { global c
  1155.     set date [open "|date +%H%M%S"]
  1156.     set Time [gets $date]
  1157.     close $date
  1158.     return "$c(scanout)$Time"
  1159. }
  1160.  
  1161. proc getpid { command } {
  1162.     set psList [open "|ps xc"]
  1163.     set pid ""
  1164.     while {[set i [gets $psList]] != {}} {
  1165.         if [regexp "$command" "$i"] {
  1166.             lappend pid [lindex $i 0]
  1167.         }
  1168.     }
  1169.     close $psList
  1170.     return $pid
  1171. }
  1172.  
  1173. proc kill_scan_command {} { global s
  1174.     set s(pid) [getpid $s(command)]
  1175.     if {"$s(pid)" != ""} { foreach i $s(pid) { exec kill -HUP $i } }
  1176. }
  1177.  
  1178. proc isinside { x y tx ty bx by } {
  1179.     if { $x >= $tx && $x <= $bx && $y >= $ty && $y <= $by } { return 1
  1180.     } else { return 0 }
  1181. }
  1182.  
  1183. proc pixelto { unit length } { global s
  1184.     return [expr $length/$s(preresolution).0*$s(c$unit)]
  1185. }
  1186.  
  1187. proc gamma_table { gamma } {
  1188.     set table 0
  1189.     for {set i 1} {$i < 256} {incr i} {
  1190.         set value [expr 255.*pow([expr $i./255.],[expr 1./$gamma])]
  1191.         append table ,[format "%0.0f" $value]
  1192.     }
  1193.     return $table
  1194. }
  1195.  
  1196. #---------------------------------------------------------------
  1197. # Procedures for Scanning : Preview and Scan
  1198. #----------------------------------------------------------------
  1199.  
  1200. proc Preview {} { global s c w
  1201.     # WHEN STOP BUTTON IS PRESSED WHILE PREVIEWING
  1202.     if $s(stop) {
  1203.         # kill scan command
  1204.         kill_scan_command
  1205.         stat_text "Scanning Preview ... Stopped"
  1206.         set s(runscan) 0
  1207.         set s(stop) 0
  1208.         $w(bt).p configure -state normal
  1209.         $w(bt).s configure -state normal
  1210.         $w(bt).q configure -state disabled
  1211.         return
  1212.     }
  1213.     # BUTTON STATE DURING PREVIEWING
  1214.     $w(bt).p configure -state disabled
  1215.     $w(bt).s configure -state disabled
  1216.     $w(bt).q configure -state normal
  1217.     if {$s(runscan) == 0} {
  1218.     # LAUNCH COMMAND-LINE SCANNNER DRIVER
  1219.         savecur cur
  1220.         setcur pre
  1221.         settop $s(o) $s(o)
  1222.         setbottom $s(maxpwidth) $s(maxpheight)
  1223.         image create photo preview -data {}
  1224.         stat_text "Scanning Preview ..."
  1225.         update
  1226.         run_scanner_driver 0 $c(prefile)
  1227.         set s(runscan) 1
  1228.     } else {
  1229.     # CHECK PREVIEWING PROGRESS
  1230.         set s(pid) [getpid $s(command)]
  1231.         if {$s(pid) == ""} {
  1232.         # PREVIEWING IS FINISHED
  1233.             set prefile $c(tkscandir)/$c(prefile)
  1234.             if { $s($s(premode)format) == "pbm" } {
  1235.                 exec convert $prefile.pnm $prefile.xbm
  1236.                 image create bitmap preview -background white -file $prefile.xbm
  1237.             } else {
  1238.                 if {$s(gamma_support)==1} { set gamma $s(pregamma)
  1239.                                    } else { set gamma 1 }
  1240.                 image create photo preview -gamma $gamma -file $prefile.pnm
  1241.             }
  1242.             set s(runscan) 0
  1243.             stat_text "Scanning Preview ... Done"
  1244.             update
  1245.             $w(bt).p configure -state normal
  1246.             $w(bt).s configure -state normal
  1247.             $w(bt).q configure -state disabled
  1248.             setcur cur
  1249.             return
  1250.         }
  1251.     }
  1252.     # REPEAT UNTIL PREVIEWING IS FINISHED.
  1253.     after $s(loopperiod) Preview
  1254. }
  1255.  
  1256. proc Scan { prefix } { global s c w l
  1257.     # WHEN STOP BUTTON IS PRESSED WHILE SCANNING
  1258.     if $s(stop) {
  1259.         # kill scan command
  1260.         kill_scan_command
  1261.         stat_text "Scanning $s(curscan) / $s(nrect) ... Stopped"
  1262.         # return to the state ready for another scanning.
  1263.         if $s(nrect) {
  1264.             $w(prev) itemconfigure $s(rect$s(curscan)) -outline $l(c3)
  1265.             $w(prev) itemconfigure $s(num$s(curscan)) -fill $l(c3)
  1266.         }
  1267.         set s(runscan) 0
  1268.         set s(curscan) 0
  1269.         set s(stop) 0
  1270.         $w(bt).p configure -state normal
  1271.         $w(bt).s configure -state normal
  1272.         $w(bt).q configure -state disabled
  1273.         return
  1274.     }
  1275.     # BUTTON STATE DURING SCANNING
  1276.     $w(bt).p configure -state disabled
  1277.     $w(bt).s configure -state disabled
  1278.     $w(bt).q configure -state normal
  1279.     if {$s(runscan) == 0} {
  1280.     # LAUNCH COMMAND-LINE SCANNER DRIVER
  1281.         if {$s(nrect) == 0} {
  1282.             stat_text "Scanning $s(curscan) / $s(nrect) ..."
  1283.             run_scanner_driver $s(curscan) $prefix-$s(curscan)
  1284.             set s(runscan) 1
  1285.         } else {
  1286.             incr s(curscan) 1
  1287.             stat_text "Scanning $s(curscan) / $s(nrect) ..."
  1288.             $w(prev) itemconfigure $s(rect$s(curscan)) -outline $l(c5)
  1289.             $w(prev) itemconfigure $s(num$s(curscan)) -fill $l(c5)
  1290.             showsize $s(curscan)
  1291.             update
  1292.             run_scanner_driver $s(curscan) $prefix-$s(curscan)
  1293.             set s(runscan) 1
  1294.         }
  1295.     } else {
  1296.     # CHECK SCANNING PROGRESS
  1297.         set s(pid) [getpid $s(command)]
  1298.         if {$s(pid) != ""} {
  1299.         # CURRENT SCANNING IS STILL IN PROGRESS.
  1300.             set csize [format "%0.1f" [expr [file size \
  1301.                           $c(tkscandir)/$prefix-$s(curscan).pnm] / 1024.0]]
  1302.             set percent [format "%0.0f" [expr $csize / $s(sizeData) * 100]]
  1303.             stat_text \
  1304.                 "Scanning $s(curscan) / $s(nrect) ... $csize / $s(sizeData)"
  1305.             set x [format "%0.0f" \
  1306.                   [expr ($s(prog_bar_wd) + 4) * $percent.0 / 100]]
  1307.             $w(prog_perc) configure -text "$percent%"
  1308.             $w(prog_bar) coords $s(sg) 0 0 $x 18
  1309.             update
  1310.         } else {
  1311.         # CURRENT SCANNING IS FINISHED.
  1312.             # notify the current scanning is finished.
  1313.             set s(runscan) 0
  1314.             stat_text "Scanning $s(curscan) / $s(nrect) ... Done"
  1315.             $w(prog_perc) configure -text ""
  1316.             $w(prog_bar) coords $s(sg) 0 0 0 18
  1317.             if $s(nrect) {
  1318.                 $w(prev) itemconfigure $s(rect$s(curscan)) -outline $l(c3)
  1319.                 $w(prev) itemconfigure $s(num$s(curscan)) -fill $l(c3)
  1320.             }
  1321.             update
  1322.             # PLAY WITH THE OUTPUT OF CURRENT SCANNING.
  1323.             make_output $prefix $s(curscan)
  1324.             if {$s(curscan) < $s(nrect)} {
  1325.             # Wait until scanner is prepared again for another scanning.
  1326.                 after [format "%0.0f" \
  1327.                 [expr $s(scantime).0 * $s(by$s(curscan)) / $s(maxpheight)]]
  1328.             } else {
  1329.             # All scanning regions are exhasted.
  1330.                 # Recover the state ready for another scanning.
  1331.                 set s(curscan) 0
  1332.                 $w(bt).p configure -state normal
  1333.                 $w(bt).s configure -state normal
  1334.                 $w(bt).q configure -state disabled
  1335.                 # EXIT loopscan
  1336.                 return
  1337.             }
  1338.         }
  1339.     }
  1340.     # REPEAT THE ABOVE UNTIL FINISHED OR STOPPED.
  1341.     after $s(loopperiod) Scan $prefix
  1342. }
  1343.  
  1344. #---------------------------------------------------------------
  1345. # Output Treatment
  1346. #----------------------------------------------------------------
  1347.  
  1348. # Supported output pipes
  1349. set c(outputtoList) { ImageEditor File Printer Fax OCR }
  1350.  
  1351. proc setoutputto { type } { global s c w l
  1352.     set c(outputto) $type
  1353.     $w(outputto) configure -text $type
  1354.     if [winfo exists .output] { destroy .output }
  1355.     frame .output -bd 5 -relief flat
  1356.     pack  .output -side right -expand yes -fill both
  1357.     window_$c(outputto) .output
  1358. }
  1359.  
  1360. proc make_output { prefix i } { global s c
  1361.     make_$c(outputto) $prefix $i
  1362. }
  1363.  
  1364. #---------------------------------------------------------------
  1365. # Image Editor
  1366. #----------------------------------------------------------------
  1367.  
  1368. #
  1369. # Configurations
  1370.  
  1371. set c(ImageEditorList) {
  1372.     { XV          xv      }
  1373.     { ImageMagic  display }
  1374.     { GIMP        gimp    }
  1375. }
  1376. set c(ImageEditor) XV
  1377.  
  1378. # ImageEditorWinmode: 0=in one window, 1=separate window
  1379. set c(ImageEditorWinmode) 1
  1380.  
  1381. foreach i $c(ImageEditorList) { set c([lindex $i 0]command) [lindex $i 1] }
  1382.  
  1383. #
  1384. # window_ImageEditor and make_ImageEditor
  1385.  
  1386. proc window_ImageEditor { wn } {
  1387.     setcur Default
  1388. }
  1389.  
  1390. proc make_ImageEditor { prefix i } { global s c
  1391.     set ImageEditor $c($c(ImageEditor)command)
  1392.     if {$c(ImageEditorWinmode) == 1 || $s(nrect) == 0} {
  1393.         set geometry "-geometry [format "+%d+%d" [expr $i*100] [expr $i*25]]"
  1394.         set file "$c(tkscandir)/$prefix-$i.pnm"
  1395.     } else {
  1396.         if {$i < $s(nrect)} {return}
  1397.         set geometry "-geometry +0+0"
  1398.         for {set files ""; set j 1} {$j <= $s(nrect)} {incr j} {
  1399.             append file " $c(tkscandir)/$prefix-$j.pnm"
  1400.         }
  1401.     }
  1402.     if {$s(gamma_support)==1} {
  1403.         switch $ImageEditor {
  1404.             xv { set gamma "-gamma $s(gamma) \
  1405.                 -cgamma $s(gamma_red) $s(gamma_green) $s(gamma_blue)"
  1406.             }
  1407.             display {
  1408.                 set gamma "-gamma $s(gamma_red),$s(gamma_green),$s(gamma_blue)"
  1409.             }
  1410.             gimp {
  1411.             }
  1412.         }
  1413.     } else { set gamma "" }
  1414.     exec sh -c \
  1415.         "$ImageEditor $geometry $gamma $file ; \
  1416.          rm -f $file" &
  1417.     stat_text "Scanning $s(curscan) / $s(nrect) ... sent to $ImageEditor"
  1418.     update
  1419. }
  1420.  
  1421. #
  1422. # Subroutines
  1423.  
  1424. proc setImageEditor { i } { global s c w
  1425.     set c(ImageEditor) $i
  1426.     set c(ImageEditor) $i
  1427. #   $w(outtype) configure -text [arrayel $c(ImageEditorList) $i 0]
  1428. }
  1429.  
  1430. #---------------------------------------------------------------
  1431. # File Output
  1432. #----------------------------------------------------------------
  1433.  
  1434. #
  1435. # Configuration
  1436.  
  1437. set file(name) "scanout-#.pnm"
  1438. set file(dir) [pwd]
  1439. set file(viewer) "xv -geometry +0+0"
  1440.  
  1441. set file(typeList) {
  1442.     { RAW  pnm  }
  1443.     { BMP  bmp  }
  1444.     { EPS  eps  }
  1445.     { GIF  gif  }
  1446.     { JPEG jpg  }
  1447.     { PCD  pcd  }
  1448.     { PCL  pcl  }
  1449.     { PCX  pcx  }
  1450.     { PDF  pdf  }
  1451.     { PNG  png  }
  1452.     { PS   ps   }
  1453.     { TIFF tiff }
  1454.     { XBM  xbm  }
  1455.     { XPM  xpm  }
  1456. }
  1457. set file(type) RAW
  1458. set file(imageonly) 1
  1459.  
  1460. foreach i $file(typeList) { set file(surfix_[lindex $i 0]) [lindex $i 1] }
  1461. set file(surfixList) "\\.pgm$|\\.ppm$"
  1462. foreach i $file(typeList) { append file(surfixList) "|\\.[lindex $i 1]$" }
  1463.  
  1464. #
  1465. # window_File and make_File
  1466.  
  1467. proc window_File { wn } { global file w l
  1468.     label $wn.ti -text "TkScan File Manager" -width 24 -pady 4 -relief ridge
  1469.     canvas $wn.sep -width 0 -height 5 -relief flat
  1470.     pack  $wn.ti $wn.sep -side top
  1471.  
  1472.     frame $wn.file -bd 1 -relief groove
  1473.     frame $wn.file.ft -bd 0
  1474.     pack  $wn.file.ft -side top -fill x
  1475.     label $wn.file.ft.l -text "File Type" -width 9 -anchor w
  1476.     menubutton $wn.file.ft.mb -menu $wn.file.ft.mb.m \
  1477.                               -width 8 -fg $l(c1) -relief ridge
  1478.     pack $wn.file.ft.l $wn.file.ft.mb -side left
  1479.     set w(filetype) $wn.file.ft.mb
  1480.     menu $wn.file.ft.mb.m -tearoff false
  1481.     foreach i $file(typeList) { set type [lindex $i 0]
  1482.          $wn.file.ft.mb.m add command -label $type -command "setFiletype $type"
  1483.     }
  1484.     frame $wn.file.fn -bd 0
  1485.     pack  $wn.file.fn -side top -fill x
  1486.     label $wn.file.fn.l -text "File Name" -width 9 -anchor w
  1487.     entry $wn.file.fn.e -textvariable file(name) \
  1488.                         -width 21 -fg $l(c1) -font $l(f1)
  1489.     pack  $wn.file.fn.l $wn.file.fn.e -side left
  1490.  
  1491.     frame $wn.dir -bd 1 -relief groove
  1492.     frame $wn.dir.l
  1493.     label $wn.dir.l.l -text Directory -width 9 -anchor w
  1494.     checkbutton $wn.dir.l.c1 -text "Image files only" \
  1495.                              -variable file(imageonly) -anchor w
  1496.     pack $wn.dir.l.l $wn.dir.l.c1 -side left -fill x
  1497.     entry $wn.dir.e -textvariable file(dir) \
  1498.                     -width 30 -relief sunken -font $l(f1) -fg $l(c1)
  1499.     frame $wn.dir.f
  1500.     listbox $wn.dir.f.b -width 28 -height 9 -relief sunken -font $l(f1) \
  1501.                         -yscroll "$wn.dir.f.s set"
  1502.     set w(dirlist) $wn.dir.f.b
  1503.     scrollbar $wn.dir.f.s -command "$wn.dir.f.b yview"
  1504.     pack $wn.dir.f.b -side left  -fill both -expand yes
  1505.     pack $wn.dir.f.s -side right -fill y
  1506.     frame $wn.dir.b
  1507.     button $wn.dir.b.1 -text view   -width 4 -pady 0 -relief ridge -command {
  1508.         if {[$w(dirlist) curselection] != {}} {
  1509.             set f [lindex [selection get] 1]
  1510.             if [file isdirectory $f] {
  1511.                 cd $f
  1512.                 set file(dir) [pwd]
  1513.                 update_dir
  1514.             } else {
  1515.                 exec sh -c "$file(viewer) $f" &
  1516.             }
  1517.         }
  1518.     }
  1519.     button $wn.dir.b.2 -text remove -width 4 -pady 0 -relief ridge -command {
  1520.         if {[$w(dirlist) curselection] != {}} {
  1521.             set f [lindex [selection get] 1]
  1522.             if [file isdirectory $f] {
  1523.             } else {
  1524.                 exec sh -c "rm -f $f" &
  1525.                 update_dir
  1526.             }
  1527.         }
  1528.     }
  1529.     button $wn.dir.b.3 -text mkdir  -width 4 -pady 0 -relief ridge -command {
  1530.         if ![file exists $file(dir)] {
  1531.             exec mkdir $file(dir)
  1532.             cd $file(dir)
  1533.             update_dir
  1534.         }
  1535.     }
  1536.     button $wn.dir.b.4 -text update -width 4 -pady 0 -relief ridge -command {
  1537.         update_dir
  1538.     }
  1539.     pack $wn.dir.b.1 $wn.dir.b.2 $wn.dir.b.3 $wn.dir.b.4 \
  1540.          -side left -fill x -expand yes
  1541.     pack $wn.dir.l $wn.dir.e $wn.dir.f $wn.dir.b -side top -fill x
  1542.     update_dir
  1543.     bind $wn.dir.f.b <Double-Button-1> {
  1544.         if {[$w(dirlist) curselection] != {}} {
  1545.             set f [lindex [selection get] 1]
  1546.             if [file isdirectory $f] {
  1547.                 cd $f
  1548.                 set file(dir) [pwd]
  1549.                 update_dir
  1550.             } else {
  1551.                 exec sh -c "$file(viewer) $f" &
  1552.             }
  1553.         }
  1554.     }
  1555.     bind $wn.dir.e <KeyPress-Return> { cd $file(dir) ; update_dir }
  1556.  
  1557.     pack $wn.file $wn.dir -side top -expand yes -fill x
  1558.  
  1559.     setcur Default
  1560.     setFiletype $file(type)
  1561. }
  1562.  
  1563. proc make_File { prefix i } { global file s c
  1564.     set scanned "$c(tkscandir)/$prefix-$i"
  1565.     # Output file name: replace # to $i
  1566.     set p [string last # $file(name)]
  1567.     if {$p >= 0} {
  1568.         set outfile [string range $file(name) 0 [expr $p - 1]]$i[string \
  1569.                                range $file(name) [expr $p + 1] end]
  1570.     } else {
  1571.         set outfile $file(name)
  1572.     }
  1573.     # Run ImageMagic's convert
  1574.     if {$s(gamma_support)==1} {
  1575.         set gamma "-gamma $s(gamma_red),$s(gamma_green),$s(gamma_blue)"
  1576.     } else {
  1577.         set gamma ""
  1578.     }
  1579.     exec sh -c \
  1580.         "convert $gamma $scanned.pnm $scanned-x.$file(surfix) ; \
  1581.          rm -f $scanned.pnm ; \
  1582.          mv $scanned-x.$file(surfix) $file(dir)/$outfile" &
  1583.     stat_text "Scanning $s(curscan) / $s(nrect) ... $outfile"
  1584.     update
  1585.     check_outfile $file(dir)/$outfile
  1586. }
  1587.  
  1588. #
  1589. # Subroutines
  1590.  
  1591. proc setFiletype { type } { global file w
  1592.     set file(type) $type
  1593.     $w(filetype) configure -text $type
  1594.     set file(surfix) $file(surfix_$type)
  1595.     set p [string last . $file(name)]
  1596.     if {$p > 0} {
  1597.         set file(name) [string range $file(name) 0 $p]$file(surfix)
  1598.     }
  1599. }
  1600.  
  1601. proc update_dir {} { global file w
  1602.     $w(dirlist) delete 0 end
  1603.     set filelist [exec ls -a $file(dir)]
  1604.     foreach i $filelist {
  1605.         if {[file isdirectory $file(dir)/$i] && $i!="." && !$file(imageonly)} {
  1606.             $w(dirlist) insert end [format " %9s  %-17s " "Directory" $i]
  1607.         }
  1608.     }
  1609.     foreach i $filelist {
  1610.         if { [file isfile $file(dir)/$i] && \
  1611.              ([regexp -nocase $file(surfixList) $i] || !$file(imageonly)) } {
  1612.             set size [expr [file size $file(dir)/$i] / 1024.0]
  1613.             $w(dirlist) insert end [format " %6.0f  %-20s " $size $i]
  1614.         }
  1615.     }
  1616. }
  1617.  
  1618. proc check_outfile { filename } {
  1619.     if [file exists $filename] {
  1620.         update_dir
  1621.     } else {
  1622.         after 1000 check_outfile $filename
  1623.     }
  1624. }
  1625.  
  1626. #---------------------------------------------------------------
  1627. # Printer
  1628. #----------------------------------------------------------------
  1629.  
  1630. #
  1631. # Configurations
  1632.  
  1633. set pr(printerList) {
  1634.     { gv  { ghostview -geometry +0+0 } }
  1635.     { lp  { lpr                      } }
  1636. }
  1637. set pr(paperList) { A4 Letter }
  1638. set pr(positionList) { Center UpperLeft UpperRight LowerLeft LowerRight }
  1639. set pr(zoomRange) {10 300 1}
  1640. set pr(xoffsetRange) {0 300 1}
  1641. set pr(yoffsetRange) {0 300 1}
  1642. set pr(printer) gv
  1643. set pr(paper) A4
  1644. set pr(position) Center
  1645. set pr(zoom) 100
  1646. set pr(xoffset) 72
  1647. set pr(yoffset) 72
  1648. set pr(autoprint) 1
  1649. set pr(c) 0
  1650. set pr(viewer) $file(viewer)
  1651.  
  1652. foreach i $pr(printerList) { set pr([lindex $i 0]command) [lindex $i 1] }
  1653.  
  1654. #
  1655. # window_Printer and make_Printer
  1656.  
  1657. proc window_Printer { wn } { global pr c w l
  1658.     label $wn.ti -text "TkScan Print Manager" -width 24 -pady 4 -relief ridge
  1659.     canvas $wn.sep -width 0 -height 5 -relief flat
  1660.     pack  $wn.ti $wn.sep -side top
  1661.  
  1662.     frame $wn.pr -bd 1 -relief groove
  1663.     label $wn.pr.l -text Printer -width 9 -anchor w
  1664.     menubutton $wn.pr.mb -menu $wn.pr.mb.m \
  1665.                          -anchor w -width 8 -fg $l(c1) -relief ridge
  1666.     set w(printer) $wn.pr.mb
  1667.     pack $wn.pr.l $wn.pr.mb -side left
  1668.     menu $wn.pr.mb.m -tearoff false
  1669.     foreach i $pr(printerList) { set printer [lindex $i 0]
  1670.         $wn.pr.mb.m add command -label $printer -command "setPrinter $printer"
  1671.     }
  1672.  
  1673.     frame $wn.po -bd 1 -relief groove
  1674.     frame $wn.po.zo
  1675.     label $wn.po.zo.l -text "Zoom" -width 9 -anchor w
  1676.     entryscale $wn.po.zo pr(zoom) {} $pr(zoomRange) 113
  1677.     pack $wn.po.zo.l $wn.po.zo.e $wn.po.zo.s -side left
  1678.     frame $wn.po.po
  1679.     label $wn.po.po.l -text Position -width 9 -anchor w
  1680.     menubutton $wn.po.po.mb -menu $wn.po.po.mb.m \
  1681.                             -anchor w -width 10 -fg $l(c1) -relief ridge
  1682.     set w(printposition) $wn.po.po.mb
  1683.     pack  $wn.po.po.l $wn.po.po.mb -side left
  1684.     menu $wn.po.po.mb.m -tearoff false
  1685.     foreach i $pr(positionList) { set position [lindex $i 0]
  1686.         $wn.po.po.mb.m add command -label $position \
  1687.                                    -command "setPrintposition $position"
  1688.     }
  1689.     frame $wn.po.xo
  1690.     label $wn.po.xo.l -text "X offset" -width 9 -anchor e
  1691.     entryscale $wn.po.xo pr(xoffset) {} $pr(xoffsetRange) 113
  1692.     pack $wn.po.xo.l $wn.po.xo.e $wn.po.xo.s -side left
  1693.     frame $wn.po.yo
  1694.     label $wn.po.yo.l -text "Y offset" -width 9 -anchor e
  1695.     entryscale $wn.po.yo pr(yoffset) {} $pr(yoffsetRange) 113
  1696.     pack $wn.po.yo.l $wn.po.yo.e $wn.po.yo.s -side left
  1697.     pack $wn.po.zo $wn.po.po $wn.po.xo $wn.po.yo -side top -fill x
  1698.     set w(xoffsetlabel) $wn.po.xo.l
  1699.     set w(yoffsetlabel) $wn.po.yo.l
  1700.  
  1701.     frame $wn.pl -bd 1 -relief groove
  1702.     frame $wn.pl.b
  1703.     pack $wn.pl.b -side top -fill x
  1704.     set w(printpagelist) $wn.pl.b.b
  1705.     listbox $w(printpagelist) -width 19 -height 6 -font $l(f1) -fg blue \
  1706.             -yscrollcommand "$wn.pl.b.s set"
  1707.     pack $wn.pl.b.b -side left
  1708.     scrollbar $wn.pl.b.s -orient vertical -command "$w(printpagelist) yview"
  1709.     pack $wn.pl.b.s -side left -fill y
  1710.     frame $wn.pl.b.f
  1711.     pack $wn.pl.b.f -side right
  1712.     bind $w(printpagelist) <Double-Button-1> {
  1713.         if {[$w(printpagelist) curselection] != {}} {
  1714.             set i $pr([$w(printpagelist) curselection])
  1715.             do_print $i
  1716.         }
  1717.     }
  1718.     button $wn.pl.b.f.1 -text Remove -width 5 -pady 2 -command {
  1719.         if {[set t [$w(printpagelist) curselection]] != {}} {
  1720.             exec sh -c "rm -f $c(tkscandir)/[lindex $pr($t) 0].pnm"
  1721.             for {set i $t} {$i < [expr $pr(c)-1]} {incr i} {
  1722.                 set pr($i) $pr([expr $i+1])
  1723.             }
  1724.             incr pr(c) -1
  1725.             update_printpagelist
  1726.             if {$t < $pr(c)} { $w(printpagelist) selection set $t
  1727.                       } else { $w(printpagelist) selection set [expr $t-1] }
  1728.         }
  1729.     }
  1730.     button $wn.pl.b.f.2 -text View   -width 5 -pady 2 -command {
  1731.         if {[set i [$w(printpagelist) curselection]] != {}} {
  1732.             set img [lindex $pr($i) 0].pnm
  1733.             exec sh -c "$pr(viewer) $c(tkscandir)/$img" &
  1734.         }
  1735.     }
  1736.     pack $wn.pl.b.f.1 $wn.pl.b.f.2 -side top
  1737.  
  1738.     frame $wn.b
  1739.     checkbutton $wn.b.0 -text Auto -variable pr(autoprint)
  1740.     button $wn.b.1 -text Print -width 21 -command {
  1741.         if {[set i [$w(printpagelist) curselection]] != {}} {do_print $i}
  1742.     }
  1743.     pack $wn.b.0 $wn.b.1 -side left -fill x
  1744.  
  1745.     pack $wn.pr $wn.po $wn.pl $wn.b -side top -fill x -expand yes
  1746.  
  1747.     setPrinter $pr(printer)
  1748.     setPrintposition $pr(position)
  1749. }
  1750.  
  1751. proc make_Printer { prefix i } { global pr s
  1752.     set tag "$prefix-$i"
  1753.     stat_text "Scanning $s(curscan) / $s(nrect) ... $tag.pnm"
  1754.     set pr($pr(c)) "$tag $s(tx$i) $s(ty$i) $s(bx$i) $s(by$i)"
  1755.     if $pr(autoprint) { do_print $pr(c) }
  1756.     incr pr(c)
  1757.     update_printpagelist
  1758.     update
  1759. }
  1760.  
  1761. #
  1762. # Subroutines
  1763.  
  1764. proc update_printpagelist {} { global pr w
  1765.     $w(printpagelist) delete 0 end
  1766.     for {set i 0} {$i < $pr(c)} {incr i} {
  1767.         $w(printpagelist) insert end [lindex $pr($i) 0].pnm
  1768.     }
  1769. }
  1770.  
  1771. proc do_print { i } { global pr s c
  1772.     set tag [lindex $pr($i) 0]
  1773.     set tx  [lindex $pr($i) 1]
  1774.     set ty  [lindex $pr($i) 2]
  1775.     set bx  [lindex $pr($i) 3]
  1776.     set by  [lindex $pr($i) 4]
  1777.     set print $pr($pr(printer)command)
  1778.     if {$s(gamma_support)==1} {
  1779.         set gamma "-gamma $s(gamma_red),$s(gamma_green),$s(gamma_blue)"
  1780.     } else {
  1781.         set gamma ""
  1782.     }
  1783.     switch $pr(paper) {
  1784.         A4     { set pwd 595. ; set pht 842. ; set offset 72 }
  1785.         Letter { set pwd 612. ; set pht 792. ; set offset 72 }
  1786.     }
  1787.     set rwd [pixelto pt [expr $bx-$tx]]
  1788.     set rht [pixelto pt [expr $by-$ty]]
  1789.     set zoom [expr $pr(zoom).0/100.0]
  1790.     set iwd [expr $rwd*$zoom]
  1791.     set iht [expr $rht*$zoom]
  1792.     if {$iwd > $pwd} {
  1793.         set iwd $pwd
  1794.         set zoom [expr $pwd/$rwd]
  1795.         set iht [expr $rht*$zoom]
  1796.     }
  1797.     if {$iht > $pht} {
  1798.         set iht $pht
  1799.         set zoom [expr $pht/$rht]
  1800.         set iwd [expr $rwd*$zoom]
  1801.     }
  1802.     set pr(zoom) [format "%0.0f" [expr $zoom*100]]
  1803.     set xspace [expr $pwd-$iwd]
  1804.     set yspace [expr $pht-$iht]
  1805.     switch $pr(position) {
  1806.         Center {
  1807.             set xoffset [expr ($pwd-$iwd)/2]
  1808.             set yoffset [expr ($pht-$iht)/2]
  1809.         }
  1810.         UpperLeft {
  1811.             if { $pr(xoffset) <= $xspace } {
  1812.                  set xoffset $pr(xoffset)
  1813.             } else {
  1814.                  set xoffset $xspace
  1815.                  set pr(xoffset) [format "%0.0f" $xspace]
  1816.             }
  1817.             if { $pr(yoffset) <= $yspace } {
  1818.                  set yoffset [expr $yspace-$pr(yoffset)]
  1819.             } else {
  1820.                  set yoffset 0
  1821.                  set pr(yoffset) [format "%0.0f" $yspace]
  1822.             }
  1823.         }
  1824.         UpperRight {
  1825.             if { $pr(xoffset) <= $xspace } {
  1826.                  set xoffset [expr $xspace-$pr(xoffset)]
  1827.             } else {
  1828.                  set xoffset 0
  1829.                  set pr(xoffset) [format "%0.0f" $xspace]
  1830.             }
  1831.             if { $pr(yoffset) <= $yspace } {
  1832.                  set yoffset [expr $yspace-$pr(yoffset)]
  1833.             } else {
  1834.                  set yoffset 0
  1835.                  set pr(yoffset) [format "%0.0f" $yspace]
  1836.             }
  1837.         }
  1838.         LowerLeft {
  1839.             if { $pr(xoffset) <= $xspace } {
  1840.                  set xoffset $pr(xoffset)
  1841.             } else {
  1842.                  set xoffset $xspace
  1843.                  set pr(xoffset) [format "%0.0f" $xspace]
  1844.             }
  1845.             if { $pr(yoffset) <= $yspace } {
  1846.                  set yoffset $pr(yoffset)
  1847.             } else {
  1848.                  set yoffset $yspace
  1849.                  set pr(yoffset) [format "%0.0f" $yspace]
  1850.             }
  1851.         }
  1852.         LowerRight {
  1853.             if { $pr(xoffset) <= $xspace } {
  1854.                  set xoffset [expr $xspace-$pr(xoffset)]
  1855.             } else {
  1856.                  set xoffset 0
  1857.                  set pr(xoffset) [format "%0.0f" $xspace]
  1858.             }
  1859.             if { $pr(yoffset) <= $yspace } {
  1860.                  set yoffset $pr(yoffset)
  1861.             } else {
  1862.                  set yoffset $yspace
  1863.                  set pr(yoffset) [format "%0.0f" $yspace]
  1864.             }
  1865.         }
  1866.     }
  1867.     set page [format "-page $pr(paper)+%0.0f+%0.0f" $xoffset $yoffset]
  1868.     set geometry [format "-geometry %0.0fx%0.0f" $iwd $iht]
  1869.     exec sh -c \
  1870.         "convert $gamma $page $geometry \
  1871.                  $c(tkscandir)/$tag.pnm $c(tkscandir)/$tag.ps ; \
  1872.          $print $c(tkscandir)/$tag.ps ; \
  1873.          rm -f $c(tkscandir)/$tag.ps" &
  1874. }
  1875.  
  1876. proc setPrinter { printer } { global pr w
  1877.     set pr(printer) $printer
  1878.     $w(printer) configure -text $printer
  1879. }
  1880.  
  1881. proc setPrintposition { position } { global pr s c w
  1882.     set pr(position) $position
  1883.     $w(printposition) configure -text $position
  1884.     if {$position == "Center"} {
  1885.         $w(xoffsetlabel) configure -fg gray
  1886.         $w(yoffsetlabel) configure -fg gray
  1887.     } else {
  1888.         $w(xoffsetlabel) configure -fg black
  1889.         $w(yoffsetlabel) configure -fg black
  1890.     }
  1891. }
  1892.  
  1893. #---------------------------------------------------------------
  1894. # Fax
  1895. #----------------------------------------------------------------
  1896.  
  1897. #
  1898. # Configurations
  1899.  
  1900. set fax(viewer) "viewfax -geometry +0+0"
  1901. set fax(numberlistfile) "$c(tkscandir)/faxnumber"
  1902. set fax(c) 0
  1903.  
  1904. #
  1905. # window_Fax and make_Fax
  1906.  
  1907. proc window_Fax { wn } { global fax c w l
  1908.     label $wn.ti -text "TkScan Fax Manager" -width 24 -pady 4 -relief ridge
  1909.     canvas $wn.sep -width 0 -height 5 -relief flat
  1910.     pack  $wn.ti $wn.sep -side top
  1911.  
  1912.     frame $wn.fr -bd 1 -relief groove
  1913.     frame $wn.fr.l
  1914.     pack  $wn.fr.l -side top -fill x
  1915.     label $wn.fr.l.l -text "Fax to" -width 10 -anchor w
  1916.     button $wn.fr.l.b -text "Number List" -command faxnumberWindow \
  1917.                                     -width 13 -padx 2 -pady 0 -relief ridge
  1918.     button $wn.fr.l.c -text "Clear" -width  5 -padx 0 -pady 0 -relief ridge \
  1919.            -command {set fax(number) "" ; set fax(recipient) ""}
  1920.     pack $wn.fr.l.l $wn.fr.l.b $wn.fr.l.c -side left
  1921.     frame $wn.fr.fn
  1922.     pack  $wn.fr.fn -side top -fill x
  1923.     label $wn.fr.fn.l -text "Number" -width 10 -anchor e
  1924.     entry $wn.fr.fn.e -textvariable fax(number) \
  1925.                       -width 20 -font $l(f1) -fg $l(c1)
  1926.     pack $wn.fr.fn.l $wn.fr.fn.e -side left
  1927.     frame $wn.fr.re
  1928.     pack  $wn.fr.re -side top -fill x
  1929.     label $wn.fr.re.l -text Recipient -width 10 -anchor e
  1930.     entry $wn.fr.re.e -textvariable fax(recipient) \
  1931.                       -width 20 -font $l(f1) -fg $l(c1)
  1932.     pack $wn.fr.re.l $wn.fr.re.e -side left
  1933.  
  1934.     frame $wn.pl -bd 1 -relief groove
  1935.     frame $wn.pl.a
  1936.     pack $wn.pl.a -side top -fill x
  1937.     label $wn.pl.a.l -text "Page List" -width 10 -anchor w
  1938.     pack $wn.pl.a.l -side left
  1939.     frame $wn.pl.b
  1940.     pack $wn.pl.b -side top -fill x
  1941.     set w(faxpagelist) $wn.pl.b.b
  1942.     listbox $w(faxpagelist) -width 19 -height 8 -font $l(f1) -fg blue \
  1943.             -yscrollcommand "$wn.pl.b.s set"
  1944.     pack $wn.pl.b.b -side left
  1945.     scrollbar $wn.pl.b.s -orient vertical -command "$w(faxpagelist) yview"
  1946.     pack $wn.pl.b.s -side left -fill y
  1947.     frame $wn.pl.b.f
  1948.     pack $wn.pl.b.f -side right
  1949.     bind $w(faxpagelist) <Double-Button-1> {
  1950.         if {[$w(faxpagelist) curselection] != {}} {
  1951.             set page $fax([$w(faxpagelist) curselection])
  1952.             exec sh -c "$fax(viewer) $c(tkscandir)/$page" &
  1953.         }
  1954.     }
  1955.     button $wn.pl.b.f.1 -text Attach -width 5 -pady 2 -command {
  1956.         attachWindow
  1957.     }
  1958.     button $wn.pl.b.f.2 -text Detach -width 5 -pady 2 -command {
  1959.         if {[set t [$w(faxpagelist) curselection]] != {}} {
  1960.             for {set i $t} {$i < [expr $fax(c)-1]} {incr i} {
  1961.                 set fax($i) $fax([expr $i+1])
  1962.             }
  1963.             incr fax(c) -1
  1964.             update_faxpagelist
  1965.             if {$t < $fax(c)} { $w(faxpagelist) selection set $t
  1966.                        } else { $w(faxpagelist) selection set [expr $t-1] }
  1967.         }
  1968.     }
  1969.     button $wn.pl.b.f.3 -text Up     -width 5 -pady 2 -command {
  1970.         if {[set t [$w(faxpagelist) curselection]] != {} && $t > 0} {
  1971.             set u [expr $t-1]
  1972.             set tmp $fax($u)
  1973.             set fax($u) $fax($t)
  1974.             set fax($t) $tmp
  1975.             update_faxpagelist
  1976.             $w(faxpagelist) selection set $u
  1977.         }
  1978.     }
  1979.     button $wn.pl.b.f.4 -text Down   -width 5 -pady 2 -command {
  1980.         if {[set t [$w(faxpagelist) curselection]] != {}
  1981.             && $t < [expr $fax(c)-1]} {
  1982.             set u [expr $t+1]
  1983.             set tmp $fax($u)
  1984.             set fax($u) $fax($t)
  1985.             set fax($t) $tmp
  1986.             update_faxpagelist
  1987.             $w(faxpagelist) selection set $u
  1988.         }
  1989.     }
  1990.     button $wn.pl.b.f.5 -text View   -width 5 -pady 2 -command {
  1991.         if $fax(c) {
  1992.             for {set pages ""; set i 0} {$i < $fax(c)} {incr i} {
  1993.                 append pages " $c(tkscandir)/$fax($i)"
  1994.             }
  1995.             exec sh -c "$fax(viewer) $pages" &
  1996.         }
  1997.     }
  1998.     pack $wn.pl.b.f.1 $wn.pl.b.f.2 $wn.pl.b.f.3 $wn.pl.b.f.4 \
  1999.          $wn.pl.b.f.5 -side top
  2000.  
  2001.     frame $wn.b
  2002.     button $wn.b.1 -text "SEND FAX" -width 12 -command sendFax
  2003.     pack $wn.b.1 -side left -expand yes -fill x
  2004.  
  2005.     pack $wn.fr $wn.pl $wn.b -side top -expand yes -fill x
  2006.  
  2007.     update_faxpagelist
  2008.     setquickmode Fax
  2009.     setquickpaper A4
  2010. }
  2011.  
  2012. proc make_Fax { prefix i } { global fax s
  2013.     set tag $prefix-$i
  2014.     pnmtofax $tag
  2015.     stat_text "Scanning $s(curscan) / $s(nrect) ... $tag.fax"
  2016.     set fax($fax(c)) "$tag.fax"
  2017.     incr fax(c)
  2018.     update_faxpagelist
  2019.     update
  2020. }
  2021.  
  2022. #
  2023. # Efax dependent procedures
  2024.  
  2025. proc pnmtofax { fn } { global c
  2026.     set if "$c(tkscandir)/$fn.pnm"
  2027.     set of "$c(tkscandir)/$fn.fax"
  2028.     exec sh -c "efix -n $of $if ; rm -f $if" &
  2029. }
  2030.  
  2031. proc sendFax {} { global fax c
  2032.     if {$fax(c) <= 0} { stat_text "sendfax: Nothing to send" ; return }
  2033.     if {$c(faxnumber) == {}} { stat_text "sendfax: Empty Fax Number" ; return }
  2034.     for {set pages "" ; set i 0} {$i < $fax(c)} {incr i} {
  2035.         append pages " $c(tkscandir)/$fax($i)"
  2036.     }
  2037.     exec sh -c "fax send $fax(number) $pages" &
  2038. }
  2039.  
  2040. #
  2041. # Subroutines
  2042.  
  2043. proc update_faxpagelist {} { global fax w
  2044.     $w(faxpagelist) delete 0 end
  2045.     for {set i 0} {$i < $fax(c)} {incr i} {$w(faxpagelist) insert end $fax($i)}
  2046. }
  2047.  
  2048. proc faxnumberWindow {} { global fax l w
  2049.     if [winfo exists .pbook] {return}
  2050.     toplevel .pbook
  2051.     wm title .pbook "TkScan: FaxNumberList"
  2052.     frame .pbook.1
  2053.     label .pbook.1.l -text "Fax Number List"
  2054.     pack  .pbook.1.l -side left
  2055.     frame .pbook.l
  2056.     set w(faxnumberlist) .pbook.l.b
  2057.     listbox $w(faxnumberlist) -yscroll ".pbook.l.s set" \
  2058.             -width 40 -height 8 -relief sunken -font $l(f1)
  2059.     scrollbar .pbook.l.s -command "$w(faxnumberlist) yview"
  2060.     pack $w(faxnumberlist) -side left -fill both -expand yes
  2061.     pack .pbook.l.s -side right -fill y
  2062.     frame .pbook.b -bd 1 -relief ridge
  2063.     bind $w(faxnumberlist) <Double-Button-1> select_faxnumber
  2064.     button .pbook.b.1 -text Close  -width 6 -pady 0 -command {
  2065.         save_faxnumberlist
  2066.         destroy .pbook
  2067.     }
  2068.     button .pbook.b.2 -text Select -width 6 -pady 0 -command select_faxnumber
  2069.     button .pbook.b.3 -text New    -width 6 -pady 0 -command {
  2070.         set fax(tmprecipient) ""
  2071.         set fax(tmpnumber) ""
  2072.         set fax(tmpinsert) end
  2073.         focus .pbook.i.1.e
  2074.     }
  2075.     button .pbook.b.4 -text Edit   -width 6 -pady 0 -command {
  2076.         if {[set i [$w(faxnumberlist) curselection]] != {}} {
  2077.            set line [$w(faxnumberlist) get $i]
  2078.            set x [string last : $line]
  2079.            set fax(tmprecipient) [string range $line 0 [expr $x-2]]
  2080.            set fax(tmpnumber) [string range $line [expr $x+2] end]
  2081.            set fax(tmpinsert) $i
  2082.            focus .pbook.i.1.e
  2083.         }
  2084.     }
  2085.     button .pbook.b.5 -text Remove -width 6 -pady 0 -command {
  2086.         if {[set i [$w(faxnumberlist) curselection]] != {}} {
  2087.             $w(faxnumberlist) delete $i
  2088.         }
  2089.     }
  2090.     pack .pbook.b.1 .pbook.b.2 .pbook.b.3 .pbook.b.4 .pbook.b.5 -side left
  2091.     frame .pbook.i -bd 1 -relief ridge
  2092.     frame .pbook.i.1
  2093.     frame .pbook.i.2
  2094.     pack  .pbook.i.1 .pbook.i.2 -side top -fill x
  2095.     label .pbook.i.1.l -text Name -anchor e -width 12
  2096.     label .pbook.i.2.l -text "Fax Number" -anchor e -width 12
  2097.     entry .pbook.i.1.e -textvariable fax(tmprecipient) -width 25 \
  2098.                        -font $l(f1) -fg $l(c1)
  2099.     entry .pbook.i.2.e -textvariable fax(tmpnumber) -width 25 \
  2100.                        -font $l(f1) -fg $l(c1)
  2101.     button .pbook.i.1.b -text "Clear" -width 6 -pady 0 -command {
  2102.         set fax(tmprecipient) ""
  2103.         set fax(tmpnumber) ""
  2104.     }
  2105.     button .pbook.i.2.b -text "Add" -width 6 -pady 0 -command {
  2106.         if {$fax(tmpnumber) != {}} {
  2107.             if ![string match end $fax(tmpinsert)] {
  2108.                 $w(faxnumberlist) delete $fax(tmpinsert)
  2109.             }
  2110.             $w(faxnumberlist) insert $fax(tmpinsert) \
  2111.                          "$fax(tmprecipient) : $fax(tmpnumber)"
  2112.         }
  2113.     }
  2114.     bind .pbook.i.1.e <KeyPress-Return> {focus .pbook.i.2.e}
  2115.     bind .pbook.i.2.e <KeyPress-Return> {
  2116.         if ![string match end $fax(tmpinsert)] {
  2117.             $w(faxnumberlist) delete $fax(tmpinsert)
  2118.         }
  2119.         $w(faxnumberlist) insert $fax(tmpinsert) \
  2120.                          "$fax(tmprecipient) : $fax(tmpnumber)"
  2121.         focus .pbook.i.1.e
  2122.     }
  2123.     pack .pbook.i.1.l .pbook.i.1.e .pbook.i.1.b -side left
  2124.     pack .pbook.i.2.l .pbook.i.2.e .pbook.i.2.b -side left
  2125.  
  2126.     pack .pbook.1 .pbook.i .pbook.l .pbook.b -side top -fill x
  2127.  
  2128.     set fax(tmprecipient) ""
  2129.     set fax(tmpnumber) ""
  2130.     set fax(tmpinsert) end
  2131.     read_faxnumberlist
  2132. }
  2133.  
  2134. proc select_faxnumber {} { global fax w
  2135.     if {[set s [$w(faxnumberlist) curselection]] != {}} {
  2136.         set line [$w(faxnumberlist) get $s]
  2137.         set x [string last : $line]
  2138.         set fax(number) [string range $line [expr $x+2] end]
  2139.         set fax(recipient) [string range $line 0 [expr $x-2]]
  2140.     }
  2141. }
  2142.  
  2143. proc read_faxnumberlist {} { global fax w
  2144.     if ![file exists $fax(numberlistfile)] {return}
  2145.     set file [open $fax(numberlistfile) r]
  2146.     while {[set i [gets $file]]!={}} { $w(faxnumberlist) insert end $i }
  2147.     close $file
  2148. }
  2149.  
  2150. proc save_faxnumberlist {} { global fax w
  2151.     set file [open $fax(numberlistfile) w]
  2152.     for {set i 0} {$i < [$w(faxnumberlist) size]} {incr i} {
  2153.         puts $file [$w(faxnumberlist) get $i]
  2154.     }
  2155.     close $file
  2156. }
  2157.  
  2158. proc attachWindow {} { global fax c s w
  2159.     stat_text "Attach: Not implemented yet."
  2160. }
  2161.  
  2162. #---------------------------------------------------------------
  2163. # OCR
  2164. #----------------------------------------------------------------
  2165.  
  2166. #
  2167. # Configurations
  2168.  
  2169. #
  2170. # window_OCR and make_OCR
  2171.  
  2172. proc window_OCR { wn } { global c w l
  2173.     label $wn.ti -text "TkScan OCR Manager" -width 24 -pady 4 -relief ridge
  2174.     canvas $wn.sep -width 0 -height 5 -relief flat
  2175.     pack  $wn.ti $wn.sep -side top
  2176.  
  2177.     frame $wn.ex -bd 1 -relief groove
  2178.     label $wn.ex.l -width 32  \
  2179.                    -text "
  2180. OCR is not implemented yet
  2181. in this version.
  2182. "
  2183.     pack  $wn.ex.l -side left
  2184.  
  2185.     pack $wn.ex -side top -expand yes -fill x
  2186.  
  2187.     setquickmode OCR
  2188. }
  2189.  
  2190. proc make_OCR { prefix i } { global s c w
  2191. }
  2192.  
  2193. #----------------------------------------------------------------
  2194. # StartUp
  2195. #----------------------------------------------------------------
  2196.  
  2197. eval destroy [winfo child .]
  2198. wm title . "TkScan"
  2199.  
  2200. set s(unit)    mm
  2201. set c(outputto)    ImageEditor
  2202. set s(premodecurrent) 0
  2203. # The user configuration file, if exists, overwrites the above assignments.
  2204. if [file exists $c(userconf)] {source $c(userconf)}
  2205.  
  2206. # Initialization of some variables
  2207. set s(nrect)    0
  2208. set s(runscan)    0
  2209. set s(curscan)    0
  2210. set s(stop)    0
  2211.  
  2212. # Launch main window
  2213. mainWindow
  2214. previewcanvas
  2215. image create photo preview -data {}
  2216. set ip [expr $s(o)-1]
  2217. $w(prev) create image $ip $ip -image preview -anchor nw
  2218. set s(rect0) [$w(prev) create rectangle 0 0 0 0 -width 1 -outline $l(c2)]
  2219. settop $s(o) $s(o)
  2220. setbottom $s(maxpwidth) $s(maxpheight)
  2221. setunit $s(unit)
  2222. setmode $s(mode)
  2223. if [regexp "ImagEeditor|File|Printer|Fax|OCR" [lindex $argv [expr $argc-1]]] {
  2224.     set c(outputto) [lindex $argv [expr $argc-1]]
  2225. }
  2226. setoutputto $c(outputto)
  2227. stat_text "TkScan v$c(version)"
  2228.  
  2229. # End of tkscan
  2230.