home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR2 / DVPG30FS.ZIP / JVMAIN.C < prev    next >
Text File  |  1993-12-05  |  102KB  |  2,719 lines

  1. /*
  2.  * jdmain.c  ver 2.1d Feburary 15, 1993
  3.  * written by Eric Praetzel
  4.  *
  5.  
  6.  May 30, 1992
  7.   - patch ATI driver (hardcoded a changable value that was changed)
  8.   - fixed VESA modes
  9.   - added ATI hi_color (32,768 color) mode as card #17 - actually sets ati_hi_color flag
  10.   - note FORCED VIDEO MODE defaults to 1024 size (now removed) --- big mistake if its a lower resolution
  11.   - ATI hi_color x size is patched to work with range checking and allow proper page selection
  12.   - added Tseng 4000 ramdac hi-color modes
  13.   - added multiple keypress detection to move multiple steps per draw
  14.   - insert mode into the user list of modes sorts by y size (assume x also increases with x)
  15.   - the user can fill the mode list with 10 of 320 * 200 if he wants - ie no checking
  16.   - took out jquant1 in ?.h file since why bother using it?
  17.   - fixed some erratic functioning in forcevga (doing something funny crossing segment boundary ??? - seems fixed
  18.  
  19.  June 7, 1992
  20.  
  21. - at version 1B
  22.   - made pallet limit if a color hits 255 --> dark areas still lighten but bright ones don't
  23.   - added file selection from a menu (and mode, shrink)
  24.   - can view one file after another without exiting
  25.   - file name mask can be used
  26.   - files names can be sorted
  27.   - a bit of help at places
  28.   - can select video mode for viewing
  29.   - can adjust panning, shrinking before view
  30.   - added color railing on brightness if a color component is going to go > 64 so colors don't wrap anymore
  31.   - added sort modes (name, date, size)
  32.   - config. file is now assumed to be in same dir as dvpeg.exe
  33.   - path, drive now changable from within program
  34.   - other directories shown with files to allow moving around
  35.   - a file name can be given at the cmd line and it is shown first
  36.   - added ability to change smoothing, dithering
  37.  
  38. - at version 1C
  39.   - put some common stuff (vidsetup, dvpeg) into dvutil.c and call it in with # include - yech but easy to do
  40.  
  41. - at version 1e
  42.   - fixed problem with 1 pass quantizing
  43.   - can ESC out of viewing now (still a bit slow at times
  44.   - custom video modes are now possible
  45.   - 1 pass/ 2 pass & quantify colors problems were fixed (whole routine was _after_ jump vectors were set)
  46.   - finally fixed boundary problem on panning
  47.   - attempts at speed were thwarted (tried jquant2)
  48.   - patched problem with switching to a drive that was in root - ie gave a:\\
  49.   - fixed video testing on hi_color - it used to generate color comp's 0 .. 64 not 0 .. 32
  50.  
  51. - at version 1g
  52.   - hi_color modes work (ATI at least).  I forgot about the 8 bit RGB components haveing to be shifted to 5 bits
  53.   - A new jrevdct routine has been put in.  Its about twice as fast as the old one.  Over a 1 min image its about 2 sec faster
  54.       The 32 bit assembler version is 4 * faster than the 16 bit C code !
  55.   - revamped default flags and put them into both menus but they are always loaded from dvpeg.cfg
  56.   - added Ahead B card
  57.   - gif viewing added (interlaced problems still & its slow )
  58.   - made special pixel plotting for VGA, streamlined ATI hi_color plotting a bit
  59.  
  60. - at version 1h
  61.   - patched wierd panning problem (if pic was rect and fit on y but no x panning bombed
  62.   - added default director into vidsetup, changed so dvpeg will autodetect
  63.   - added ability to goto a directory in dvpeg using F6
  64.   - seperated out video drawing to rewrite in assembler
  65.   - any errors are now handled properly without program exit
  66.   - ESC pressing will halt for 1 char press, but if ESC from menu you hop back immediately
  67.   - added beep on error (low freq) , done (higher freq)
  68.   - added code to force VGA not hi_color on GIF (will not work with custom definations)
  69.   - j_copy_block_rows, j_copy_samp_rows was changed to use _fmemcpy which is a lot faster
  70.   - changed jzero_far to _fsetmem()  for Borland C - nice speed improvement
  71.   - changed copying to buffer from inner drawing loop to _fmemcpy on super_vga for speed - can't do on hi_color due to bit packing
  72.  
  73. -at version 2.0 [beta]
  74.   - converted jvdraw to assembler and doubled the speed
  75.   - speed up gifs, 1 pass quantize by converting jpeg routines to assembler and tuning for 32 bit
  76.   - threw in 24 bit video support for Tseng card
  77.   - fixed panning in 286 version - need to recompile and hand tweak for 386 version
  78.  
  79. -at version 2.a
  80.   - added patch to vidsetup use vidsetup -X to aviod video testing --> it trashes some computer's CMOS!! (Paradise with 1M)
  81.   - fixed VESA driver
  82.   - revamped so that you have to run vidsetup first
  83.   - only the usable modes are stored in the file (ie dvpeg does not have access to all modes)
  84.   - added 24 bit modes and revamped drivers to make the 24 bit modes standard access to bank-switching
  85.   - put trident "cards" (8900, 8800) together and put hi_color modes under the respective card
  86.   - revamped video setup so that AX, BX is given simplifying a lot of the setup for newer cards
  87.   - video card lists are now of variable length and easy to expand - no more double indexing to get a video cards resolution (X, Y size ...)
  88.   - video mode resolution (8, 15, 24 bit) are now in the video data - it is no longer dependant upon location in the list
  89.   - changed config file load/save format to save all video info required for each mode + info for vidsetup to find custom modes
  90.   - added unix'y passing ie dvpeg e:*.jpg will do just that
  91.  
  92. - at version 2.b
  93.   - added tint .. for hi-color (hit normal tint controls)
  94.   - added multiplier for tint controls ie F2 = 2* normal tint amount
  95.   - hi-color is saved as 24 bit for better contrast controls ..
  96.   - setup is done for a preference of tint, contrast, bright to effect pic when its first loaded
  97.   - added Diamond Speedstar X24 (S3??) code  --> Can't detect the card though
  98.  
  99. - at version 2.1
  100.   - fixed up file name, path, drive passing - its now fully UNIXish
  101.   - problem  d:\gifs\new is new a path or a file ??? how tell ??
  102.   - non-256 color modes now have the panning on or off  (need to be able to flag it differently for tint, bright ...
  103.   - finally (?) fixed the Speedstar code
  104.   - fixed the VESA driver again (table was reversed)
  105.   - taking a guess that S3 based cards are VESA compatable  ie AX was same as VESA
  106.   - added N, P for next, previous picture without going thru the text screens
  107. - at version 2.1
  108.   - added Paradise, Ahead B modes
  109.   - custom text mode support ie 50 line, 132 col ...
  110.   - seperated drawing routines so that I can put them to assembler and leave them alone
  111.   - fixed bug in Tseng 3000 detection
  112.   - added Trident hi-color modes  ??????  (did I ????)
  113.   - fixed custom video mode sticking on Ahead A
  114.   - changed 24 bit modes from 1920 bytes/row to 2048 (as per SpeedStar 24X specs
  115.   - added (correct ?) 24 bit vesa mode
  116.   - went to Borland C 3.1
  117.   - dropped all .asm versions of the IJG C modules (only 1% speed loss)
  118.   - went to version 4 of the IJG code
  119.   - tried dynamic memory alloc for file data records - very slow + problems reusing
  120.   - went to a block alloc of fixed size for file data records from far memory (ie possible to make larger, smaller during execution
  121.   - all jpeg warnings are turned off so you will just get a junk file as it tries but no error msg will be printed unless its unrecoverable
  122.   - beep bit now turns off beep when picture is loaded
  123.   - error messages can be turned off but it will still beep on error and pause for a key
  124.   - HOME, END do that for the file list
  125.   - added delete command so can delete files with Del key
  126.   - slide show is added (10 files max), s = show, S = continous loop
  127.   - added F7 function to change extra defaults
  128.   - added a flag to enable or disable hi-color tint ... controls on jpegs (ie on = buffering = panning ... )
  129.   - the code size now exceeds 64k and so I had to move upto a medium memory model
  130.   - problems with the new memory model means I had to combine point.asm and banks.asm to get it to compile (??? why ???)
  131.  
  132. -at version 2.1b
  133.   - added picture X axis centering when viewing (only if picture is smaller than the screen)
  134.   - speed up drawing by simplifying looping in panning
  135.   - split 256 color panning for better speed
  136.   - tried a S3 driver - may not work (ie don't know if numbers were hex or dec
  137.   - if greyscale then drop to a 256 color mode
  138.   - seperated panning from tint ...  for better speed
  139.   - added support for wider file (ie file size) info packets on text screen with file info
  140.  
  141. -at version 2.1c
  142.   - if store_hicolor_in_24 is set use 24 bit storage and enable panning on JPEG always
  143.   - if the jpeg is < screen and 24 bit storage is not set then don't buffer image - if its bigger buffer for panning
  144.   - can sort in ascending or descending order
  145.   - new file sort routines useing bisection search for speed
  146.   - new file structure with an extra byte per file to include things like a slide show flag => slide show has unlimited # of files but you can't set an order of viewing
  147.   - 'A' selects all files for slide show
  148.   - 24 bit fixed and working with ATI Wonder XL24
  149.   - use memcpy for copying lines to graphics screen if shrink = 1 (hi-color, 24 bit, vga)
  150.   - to speed up file list generation I went to a memcpy instead of copying the struct element by element
  151.   - changed the contrast, tint controls to remove 1 multiply each - that just leaves 1 divide (each) to slow it down on the 15, 24 bit modes
  152.   - can have multiple file masks (5 currently) - hit 'del' when entering erases the current mask
  153.   - R repaints a picture ie setups up video mode and redraws - when in picture viewing mode - only if panning is on
  154.   - r is like R but does not reset the contrast, bright, tint controls
  155.   - if multiple arguements are given it is assumed that they are file names and will be shown in order (wait for keypress between)
  156.   - if a '-' arguement is given after the file name(s) dvpeg will exit and not go into the menu
  157.   - if you try to enlarge (ie hit ++) when panning is on and zoom is 1 then the you will zoom to the next video mode
  158.   - if try to shrink 5 times and panning is on the video mode will change to the next largest
  159.   - 24 bit tint controls by going thru video memory - ie does not need a buffered copy of the image
  160.   - 15 bit tint controls by working on the video memory directly
  161.  
  162. - at version 2.1d  Feb 15, 1993
  163.   - fixed problem with dvpeg.cfg file format (file was getting corrupted
  164.   - fixed some tinting problems when working on the memory
  165.   - went to a faster tinting equation
  166.  
  167. - at version 2.1e  Feb 26, 1993
  168.   - new IJG V4A code (greyscale 35% faster, color 11%, 13% faster for 1 pass, 2 pass)
  169.   - new global vars for drawing routines which are recalculated after mode change ....
  170.      - this removed calc's from drawing routines & tests since the picture and screen boundaries were defined
  171.      - this prepares the way for multiple windows with a struct describing each
  172.      - this also removed if tests from drawing routines => bit faster
  173.   - added a shrink lock-out flag and make the shrink automatic (ie it can't be set anymore)
  174.      - the shrink to fit only works if panning is off
  175.   - can shrink gifs now (as they are being loaded without the panning turned on)
  176.      - this will not work on interlaced gifs
  177.  
  178. - at version 2.2  Feb 22, 1993
  179.   - fixed panning problems on some hi-color modes & 24 bit mode
  180.   - fixed problem of getting a list full of 320 * 200 if you only have 256 color modes
  181.   - reformatted screen info so that the file names are right centered and the file length are left centered and aligned
  182.   - if 24 bit panning is on for hi-color then panning is always on
  183.   - hitting E (instead of enter) will use 'Editing mode' ie all buffering of the picture is on and it is 24 bit for hi-color tint controls
  184.   - partially added viewing defaults file (Save, Delete)
  185.   - fixed problem with 24 bit mode that crosses boundaries (ie don't paint that pixel !)
  186.   - shrink to fit only works if it is enabled and panning is off
  187.  
  188. - at version 2.3 March 1, 1993
  189.   - fixed quantizing bug
  190.  
  191. - at version 2.4 March 1, 1993
  192.   - vidsetup compiled incomplete (can't change file buffer array)
  193.   - moved all function declerations to extern.h
  194.  
  195. - at version 2.5 March 8, 1993
  196.   - fixed some panning problems with shrink (again)
  197.   - prev. version did not have vidsetup compiled properly (could not change size of the file list)
  198.   - delete will delete files in any directory not just startup directory
  199.   - added screen clear option (may not clear last byte of 64k block)
  200.   - shrink can be manually changed again
  201.   - on 2 pass quantizing it does not change to graphics screen till the drawing starts -> improves slideshow
  202.   - if viewing defaults for a file are saved any old defaults are deleted first - stops the file from getting very big
  203.   - menu items only cause recalculation of screen size, directory file list if they effect them (new flag variable)
  204.   - if doing a slide show the the 2nd pic will be have the header read and 1 pass of the 2 pass quantize will be
  205.       done before the delay for the next pic. starts -> better response on 2 pass video cards
  206.   - added new jrdgif routine (better error handling than the old one I had)
  207.  
  208. - at version 2.5b June 6, 1993
  209.   - adding R,B flip in R,G,B in 24 bit mode only and flipped it from what it was
  210.   - adding 16 bit code routines + panning ....
  211.   - added Cirrus card support
  212.   - VESA mode needs to be fixed - granuality was added but it still does not work with some drivers
  213.  
  214. - at version 2.6 June 23, 1993
  215.   - in dvpeg and vidsetup the first arguement is assumed to be the config file
  216.   - the config file format has changed so that the first char is a marker which will seperate it from a gif/jpeg file
  217.   - updated Cirrus driver to enable extended regs (maby this will make it work?) and updated modes from SVGAKIT31.zip
  218.   - slide-show was changed so that the showing order is the same as the order of selection
  219.   - added 15,16 bit mode numbers for S3, Cirrus, Trident, Tseng 4000, NCR
  220.  
  221. -at version 2.7 June 24, 1993
  222.   - fixed Tseng 4000 support for 15,16,24 bit
  223.  
  224. - at version 2.8 June 28, 1993
  225.   - fixed mistake I made in the Tseng 4000 support
  226.   - fixed mistake in Cirrus mode list (640 * 480 * 256 only)
  227.   - fixed VESA patch (ie making buffer 260 bytes instead of 256 to give a buffer - the pop 260 bytes was still set to 256)
  228.  
  229. - at version 2.8a June 29, 1993
  230.   - added ability to lock the view into one Y resolution - also settable in vidsetup (stored in dvpeg.cfg file)
  231.       This locks the Y size and not a certain mode
  232.   - added ability to force 50 line text mode
  233.   - when dvpeg, vidsetup is run it tests and preserves 50 line text modes
  234.   - Cirrus mode numbers were wrong -fixed 16 bit works!!
  235.   - moved message beeping so warnings will be caught
  236.   - redid the page formatting infomation to better fill pages with file names
  237.   - fixed up video mode detection to save if 8*8 char gen was used (ie 50 line mode)
  238.   - ***** 132 column text modes are not recognized *******
  239.   - a new video mode selection routine to pick the best of 24,16,15,8 bit modes ie it starts at the highest resolution and works down
  240.   - selecting a file for slide-show advances the cursor to the next file
  241. - at version 2.8b, July 5, 1993
  242.   - dvpeg (386) was compiled wrong - something was strange in the JPEG code
  243.   - added a main check_keybd() keyboard test while decoding picutures
  244.   - video_cards[] gets cleared to -1 (solve strange insertion problems)
  245.   - the zoom in/out now uses video_cards and will search for any modes in the list not just the ones in ok_mode
  246.   - fixed possible problem with passing file names in
  247.   - changed most of the readgif code to near functions (no measureable speed boost)
  248.   * compiled a small model version of the jpeg code, 17% faster on 2 pass, 5% faster on 1 pass!
  249.   - put jdmcu.c into jrevdct.c to have j_rev_dct work as a near function
  250.   - put j_rev_dct, decode_mcu, fill_bit_buffer as near functions (changes to jdhuff.c, jrevdct.c, jdmcu.c)
  251.   -> decode_mcu could not be near unless the cinfo->methods->entropy_decode is changed to near in all declarations
  252.   - tried new optimization "common subexpression -> locally"; smaller file but 2 sec slower on a 1 min. 2 pass JPEG
  253.   - tried new optimization "no pointer aliasing"; smaller code; 4 sec faster on a 1 min 2 pass JPEG
  254.  
  255. - at version 2.9, July 12, 1993
  256.   - modified jjrdgif.c to try to get more speed using flow-thru code ie the
  257.       rarely used conditions were coded with goto's ==> no measurable speed difference on 12 sec picture
  258.   - added an adjustable buffer for reading the input file (sped up GIF by 15%, no effect on JPEG for my hard drive)
  259.   - changed graphic screen clear routine (it did not clear 1 byte at the end of each 64k block)
  260.   - fixed mode locking to use Y size and not mode numbers
  261.   - moved JPEG_BUF_SIZE from jconfig.h into the F7 buffer size menu to allow different sizing on the JPEG buffers
  262.      -> GIF buffering is at the file stream while JPEG has its own built in buffer
  263.      -> default is 16k (was 4k in IJG JPEG code); minimum = 4k; max = 32k
  264.   - a "twiddle factor" was added to the F7 menu.  If the picture is twiddle_factor pixels bigger than the image
  265.      then the next bigger mode will be chosen.  ie this prevents the shrinking of images that are slightly bigger
  266.      than the screen resolution
  267.   - changed the Next, Previous picture option so that you will see the menu if it is turned on
  268.   - added 4DOS file description reader (ie DESCRIPT.ION file)
  269.   - added Targa, PBM image formats
  270.   - changed buffering so that file buffering is performed for everything except JPEG
  271.   - changed file reading so that all non-JPEG images use the same reading routine
  272.       - ie each file format just has to provide a routine to retune 1 line
  273.   - bottom-up targa images will not buffer properly for panning like interlaced gifs because they are drawn from the bottom up
  274.   - fixed sort by date (subtraction was wrong with the year/month/day bit ordering)
  275. - at 2.9a August 26/93
  276.   - added ability to force panning always on
  277.   - updated vidsetup so that you can fill screen with one color
  278.   - when viewing JPEGs sometimes no non SVGA modes would show up due to lack of initialization of cinfo->color_map_present
  279.   - added ability to lock out all SVGA modes smaller than the lowest 15/16/24 bit mode ie if you want > SVGA but also SVGA for very large pics
  280.   - revamped shrinking to work better (ie 1200 * 800 uses 640 * 480 in shrink = 2 instead of 1024 * 768 in shrink = 2)
  281. - at 2.9b Sept 10/93
  282.   - added drawing title on the picture screen or a defined text string
  283.   - increased the number of file masks from 5 to 8
  284.   - increased shrinking from 1/4 max to 1/5
  285.   - changed some vars into #define for simplicity
  286.   - revamped the entire front end to accept parameters to set every option and then some
  287.   - can print title to center top of screen (setable on/off)
  288.   - can use a command line full of response files as arguements
  289.   - modified sections to use the flag  "small_viewer" to lock out the
  290.       F1 .. F7 options for a smaller viewer exe for the University research group
  291.   - turned off crossblock smoothing in jconfig.h so that it is not compiled
  292.   - removed "edit mode" ie the ability to save 15/16 bit modes as 24 to allow accurate
  293.       tint/bright/contrast controls to be performed for saving -> reduced complexity for a probably little used feature
  294.       -> this allows me to simplify the JPEG code so that it tosses out 15/16/24 bit code and does
  295.           not have the problem of haveing to do the 15/16 to 24 and 24 to 15/16 shuffle
  296.   - grayscale JPEG now uses no quantization for a 25% speed boost
  297.   - QPEG was just released and is 2* faster than my viewer for JPEGs!
  298.   - removing panning, shrinking, tint controls (all on initial loading) speeds up viewing 15%!
  299.   - wrapping output routine (15 bit) into ycc_rgb_convert showed no measureable difference in speed!
  300.   - there are no RGB format files so don't need to use dummy 3 variable copy in JPEG code
  301.   - first JPEG is about 4% faster than viewing the 2nd file!  This is reset by viewing a GIF!
  302.   - added ability to lock the shrink at any ratio
  303.   - removed variable JPEG_BUF_SIZE -> it caused strange performance ie slowing down after first picture,
  304.       and seemed to be _slower_!!  Plus it can not accomadate much memory out of the near stack
  305.   - fixed JPEG_BUF_SIZE to 8k (16k is probably too large, used to be 4k)
  306.   - updated VESA driver with some code from SVGAkit  (works better now??)
  307.   - tweaked the line ordering of jrevdct.c for smaller (faster?? not measurable) code
  308.   - adjusted pallet writing routine to search for max, min brightness colors -> to use for text drawing
  309.   - merged my JPEG output routines into the jdcolor.c routine ycc_rgb_convert for greater speed
  310.      - but this means that there is no shrinking upon initial loading of the image (can be done later)
  311.      - speed: initial 48 sec, remove shrinking 44 sec; merge ycc_rgb_convert & drawing 46 sec, merged & no shrink 44.5
  312.      -        merged & write to buffer 40 sec! 17% speed boost + only 4 extra sec to buffer the image
  313.      - * this was only for 15 and 16 bit modes NOT 24 bit (possible but not testable right now)
  314.      -        removed tinting went from 40.2 to 36 sec, installed tint bypass if its not there for 36s without, 40 sec if it is done
  315.      ->>>  net 25% increase in 15 and 16 bit speeds!
  316. * VGA is only for JPEG, can be anything on GIF, Targa, PNM but it will be crap
  317.   - added VGA as the last card
  318.   - changed video card resolution to include 16 color, changed to all defines, ie SVGA != 0 any more - check viewdef.h
  319.   - merged 15 & 16 bit drawing routines for everything but JPEG
  320.   - moved 24 bit routine for JPEG in ycc_rgb_convert in jdcolor.c
  321.   - added S/W zoom of *2, *3, *4 for hi-color, 256 color => revamped video calculation causing errors on panning ...
  322.   - redid all panning calculations to use center of the image, ie zooming in/out will stay centered
  323.   - added -quiet option to vidsetup so that it prints nothing and saves everything to the cfg file
  324.   - added remapping function to show interlaced, upsidedown Targas the right way
  325.      -> does not work for interlaced GIF yet
  326.   - added flag to enable/disable clearing before redraw in panning (ie clean up in cases like shrinking image
  327.   - if no config file exists then vidsetup is automatically run in the -quiet mode
  328.   - added switching so that if hi-color modes exist SVGA will not be chosen
  329.      and if SVGA modes exist the VGA ones will be ignored -> in autodetection
  330.   - VGA quantizing ie 256 colors -> 16 grayshades is very crude - should use histogram
  331.   - changed VESA granularity once again, according to a guy in France this works on his card
  332.   - tested on a 24 bit video card -> everything works; needed casts to unsigned to make shifting work
  333.   - 16 bit ???  video card died
  334. - at 3.0 Nov 4/93 (finally)
  335.   - redid graphics routines again - centeral line drawing routine to simplify it all
  336.   - images now center vertically if they are > screen
  337.   - added shrinking back to initial loading of JPEGs - but it is 5+% slower than non-shrinking
  338.   - _all_ drawing is now by lines -> ie if zoom/shrink the drawing is to a buffer which is copied to the screen
  339.      -this saves individual address calculations and allows much faster drawing
  340.      -the cost of this was an extra line (maximum 800 * 3 = 2400 bytes) of memory used
  341.   - new row-drawing routine solves problem of not drawing pixels at 64k boundaries
  342.   - S/W zooming is greatly sped up with the line-buffering now used
  343.   - added S/W patch from Tom for 2 pass quant to stop strange colors from appearing
  344.   - added ability to quantize grayscale JPEGs to 16 colors or to just use linear mapping (yech but 20% faster)
  345.   - added back in, the ability to simply pass a path and file mask without using the command line options
  346. - at 3.0a Nov 7/93
  347.   - fixed bug in 16 color mode zooms
  348.   - sped up 15/16 bit tint by moving shifting operations into color table (for red)
  349.   - removed 1 pass quantizer from the reduced version of dvpeg (ie use quick and dirty reduction to 16 shades)
  350.   - speedup reverse DCT by using 16 bit math -> 386 on 15 bit display is 11% faster
  351.      -> 286 is 40% faster!  almost at 386 speed
  352.   -> 16 bit math uses CONST_BITS = 4; PASS1_BITS = 0 for minimum error
  353.   - added flag to allow 16 color on VGA modes instead of grayscale (JPEG only)
  354.   - fixed panning problem on 16 color modes
  355. - at 3.0b Nov 8/93
  356. 3.0c ??
  357. 3.0d ??
  358.   - converted jrevdct.c to assembler and sped up 3% by editing assembler in reverse_dct
  359.   - replacing multiplies in j_rev_dct with shift & add had no effect
  360.   - changed picture file to use DOS share, so if the file is being used by another application we will (untested) fail on the reading of it
  361.   - changed range limiting to use 1/2 the number of comparisons -> 15/16/24 bit JPEG, tinting speed up
  362.   -> removed VESA patch again to see if it works for a user!
  363.   - added VESA driver (bankswitch and init code) from QPEG 1.0d -> it looks like SVGA code
  364.      -> it works with newer VESA cards!
  365.   - numerous changes to vidsetup to support ESC to exit from commands, > 24 line modes and variable menu sizes
  366.   - added extended 16 color modes for SVGA cards (ie 800 * 600, 1024 * 768, 1280 * 1024)
  367.   - changed 256 to 16 color pallet remapping to use  bright = 0.3 red + 0.6 green + 0.1 blue instead of R+G+B
  368.   - added shrinking and pannning of interlaced GIFs
  369.      -> removed it again;  it took hours if it was buffered to disk!!
  370.   - changed far pointers to FAR for GCC compatability
  371.   - change jrevdct.c to do IDCT into far data structure to avoid copying to it later
  372.       -> there was not speedup because of the complex column pointer arithmatic
  373.   - added fast up_sample code that uses a square filter and not a triangular one -> 15% speedup
  374.       -> this is switchable with the high/medium quality control
  375.       -> this can add errors upto 40% on 0.2% of the pixels and the boundary ones may have large errors as well
  376.       -> most errors (aprox. 94%) will have errors < 3% due to the filtering -> this is on par with the 16 bit math errors
  377.   - changed jdsample column counters to use int not long
  378.   - changed jdcolor green component generation to use 1 table lookup -> 3% speedup, on +/- 2 maximum error on components
  379.       -> added it to 15/16/24/general colorspace conversion routine
  380.   - tried speeding up jdcolor by editing assembler but not much gain since I only removed inter-register moves ie very fast therefore no gain
  381.   - thinking of merging lookuptables in jdcolor to save pointer generation -> better if pass them in a R,G,B tripplets in one data stream
  382.   - sped up another 3% in jdsample for h2v2 by using a string copy on successive rows
  383.   - removed upsampling of h2v2 image and modified 1 pass, 15 bit to use non-upsampled data for 20% speedup
  384.   - modified buffering so that 2 lines are simultaneously writable to the screen buffer -> speeds up h2v2 color conversion
  385.   -> tint controls for a 800 * 600 JPEG (ie tests to see if tint as load) take 0.5 sec
  386.   - added speedups to 16 bit modes
  387.   - tried to speedup jdcolor.c by compiling to assembler and using fs,gs regs -> no measurable change!
  388.   -> tests {hi/med quality & {untinted, tinted}} = {{28.6, 33.2}, {22.0, 26.6}}
  389.   - modified flood fill video test to set only 1 color and all others to background -> better test
  390.   - fixed svgamode() because DI was trashed by VESA testing
  391.   - redid video modes so that 320 * 200 was only under VGA and mode selection was better (ie 4 bit only added if necessary)
  392.   - redid the interface on vidsetup a bit to show cursor (inverse) and selected modes (as red) as well as all video cards used (in red)
  393.   - changed file selection so that a zero length file is now 1 byte long -> this allows deleting, and it will not appear as a directory
  394.   - fixed minor bug in sizing the F3 window
  395.  -> removed fast drawing of two lines at once -> bugging panning on large images ie picture buffer has some bad lines! ie junk
  396.  -> panning problem, if picture dimension < screen then the panning controls are reversed
  397. - at 3.0e Nov 30/93
  398.   - changed gif decoding pointers to near -> no speedup [ uses aprox 16k of near space ]
  399.   - changed targa input file pointer to global for a bit of speed; also cleaned up static vars by removing unused ones
  400.   - added more VESA 15,16,24 bit modes
  401.   - removed VESA duplicate 640 * 480 mode that had a different line length, VESA length detection works with good VESA drivers
  402.   -> the 16 bit modes work with univbe!  -> first proof that they really work
  403.   - fixed H?V? JPEG detection -> will work as follows: H2V2 is only true for {{1,1},{2,2},{2,2}}
  404.      H1V1 is only true for {{1,1},{1,1},{1,1}}  -> all else is considered H2V1
  405.   - brightest color selection will not only search first 16 colors for VGA modes (used to search all 256)
  406.   - 16 color modes now use the normal force grayscale and 1/2 pass quantize variables instead of dedicated ones
  407.   - sped up VGA (16 color) panning by a factor of 2 using memory moves (by line) [ still 2* slower than QPEG panning! ]
  408.      -> It could be sped up a lot if the zoom option was not used; that would explain the 2*
  409. - at 3.0f Dec 4/93
  410.  
  411.  
  412.   -  This will be the last vesion as I will be going to SVGAkit for the graphics
  413.  
  414.   - VGA quantizing ie 256 colors -> 16 grayshades is very crude - should use histogram
  415.  
  416. To do:
  417.   - fix up reordering of interlaced GIFs during panning
  418.   - need tint for all pans, ie load a prev. tinted image, pan it -> no tints since buffered copy is not tinted
  419.   - 1 pass dithering ??
  420.   - add wrapping of file selection from left to right and vise-versa?
  421.   -15/16/24 bit modes will tint the image if redrawn from the buffer
  422.  
  423. Problems
  424.  - clearning of VGA screen is done by resetting video mode -> better way??
  425.  - need cleanup of viewing defaults ie removing multiple declerations for one picture
  426.  - can't free and create new file_info structure - ie if you try the system halts with a memory alloc. error
  427.  - 15/16/24 bit does not tint when it redraws
  428.  
  429.  
  430.  
  431. To add
  432.  - add support so that interlaced gifs can be shrunk, panned ....
  433.  - large screen sized buffer for slide show ie decode into buffer while the picture is pausing (how alloc the far memory ??? without getting upset by IJG code?)
  434.  - add selectable colors for file info
  435.  - rotate by 90 deg??
  436.  - still have to figure out Cirrus card
  437.  - problem with Compaq, Cirrus? bank selector ???
  438.  *
  439.  */
  440.  
  441. #include "viewdef.h"            /* definations for the viewer */
  442. #include "extern.h"        /* external declerations for viewer plus IJG includes */
  443. #include <share.h>
  444.  
  445. #ifdef INCLUDES_ARE_ANSI
  446. #include <stdlib.h>        /* to declare exit() */
  447. #endif
  448. #ifdef NEED_SIGNAL_CATCHER
  449. #include <signal.h>        /* to declare signal() */
  450. #endif
  451.  
  452.  
  453. /* define mode parameters for fopen() */
  454. #define READ_BINARY    "rb"
  455. #define WRITE_BINARY    "wb"
  456.  
  457. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  458. #define EXIT_FAILURE  1
  459. #endif
  460.  
  461.  
  462. #include <dir.h>
  463. #include <string.h>
  464. #include <dos.h>
  465. #include <conio.h>
  466. #include <setjmp.h>
  467. #include <alloc.h>
  468. #include <time.h>
  469.  
  470. void parse_path(char * arg);
  471.  
  472. extern unsigned _stklen = 7000;
  473.  
  474. #include "jvsetup.h"            /* constants viewer */
  475.  
  476.  
  477. /* Neat little trick to do a jump and clean up stack */
  478. jmp_buf setjmp_buffer;
  479.  
  480. static external_methods_ptr emethods; /* needed for access to message_parm */
  481.  
  482.  
  483. JSAMPARRAY patch_colormap;    /* color map pointer for when I need to create a fake colormap */
  484.  
  485. int no_warning = 0;        /* flag to indicate that the error message is not a warning but a fatal error */
  486.  
  487.  
  488. /*
  489.  * Signal catcher to ensure that temporary files are removed before aborting.
  490.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  491.  * see -Dsignal_catcher=_abort in CFLAGS.  Talk about bogus...
  492.  */
  493.  
  494. #ifdef NEED_SIGNAL_CATCHER
  495.  
  496. GLOBAL void
  497. signal_catcher (int signum)
  498. {
  499.   prep_for_exit();
  500.   printf("Severe exit from signal_catcher\n");
  501.   emethods->trace_level = 0;    /* turn off trace output */
  502.   (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  503.   exit(signum);
  504. }
  505.  
  506. #endif
  507.  
  508.  
  509.  
  510.  
  511. /* This routine is used for any and all trace, debug, or error printouts
  512.  * from the JPEG code.  The parameter is a printf format string; up to 8
  513.  * integer data values for the format string have been stored in the
  514.  * message_parm[] field of the external_methods struct.
  515.  
  516.  *  If the message is of 0 length then just clean up and pass thru
  517.  *  If the 1 char message is E then it is an ESCape from viewing a pic
  518.  *  If the message if of 1 char length or > then wait for at least 1 keypress
  519.  *  If it is 1 char and beep is off then don't beep but pause
  520.  * - always beep & only give msg if requested
  521.  */
  522.  
  523. METHODDEF void
  524. trace_message (const char *msgtext)
  525. {
  526. if ( (strlen(msgtext) > 1) ||
  527.     (strlen(msgtext) == 1 && (view_defaults & beep_on)) && do_slide_show == 0){
  528.     sound(45);
  529.     delay(450);
  530.     nosound();
  531.     }
  532.  
  533. if (do_slide_show == 0 && no_warning == 1){
  534.     if (strlen(msgtext) >= 1 ) getch();        /* pause if no message requested so that the picture stays on the screen */
  535.     if (defaults & error_msg_on && (strlen(msgtext) > 1) ){
  536.         setup_text_screen();
  537.         init_screen();
  538.         open_window(50, 12);
  539.         cprintf(msgtext,
  540.             emethods->message_parm[0], emethods->message_parm[1],
  541.             emethods->message_parm[2], emethods->message_parm[3],
  542.             emethods->message_parm[4], emethods->message_parm[5],
  543.             emethods->message_parm[6], emethods->message_parm[7]);
  544.         cprintf("\n\r\nMemory left in near heap:\r\n    %lu bytes\r\n",(unsigned long) coreleft());
  545.         cprintf("Bytes above highest block in far heap:\r\n    %lu bytes\r\n",farcoreleft());
  546.         cprintf("Hit any key.\r\n");
  547.         getch();
  548.         }
  549.     }
  550. no_warning = 0;
  551. }
  552.  
  553.  
  554.  
  555. /*
  556.  * The error_exit() routine should not return to its caller.  The default
  557.  * routine calls exit(), but here we assume that we want to return to
  558.  * read_JPEG_data, which has set up a setjmp context for the purpose.
  559.  * You should make sure that the free_all method is called, either within
  560.  * error_exit or after the return to the outer-level routine.
  561.  */
  562.  
  563. METHODDEF void
  564. error_exit (const char *msgtext)
  565. {
  566. no_warning = 1;        /* signal trace message routine that this is no warning but a fatal message */
  567.  
  568. trace_message(msgtext);    /* report the error message */
  569. (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  570. longjmp(setjmp_buffer, 1);    /* return control to outer routine */
  571. }
  572.  
  573.  
  574.  
  575. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  576. /* keyword is the constant keyword (must be lower case already), */
  577. /* minchars is length of minimum legal abbreviation. */
  578.  
  579. int keymatch (char * arg, const char * keyword, int minchars)
  580. {
  581.   register int ca, ck;
  582.   register int nmatched = 0;
  583.  
  584.   while ((ca = *arg++) != '\0') {
  585.      if ((ck = *keyword++) == '\0')
  586.         return FALSE;        /* arg longer than keyword, no good */
  587.      if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  588.         ca = tolower(ca);
  589.      if (ca != ck)
  590.         return FALSE;        /* no good */
  591.      nmatched++;            /* count matched characters */
  592.   }
  593.   /* reached end of argument; fail if it's too short for unique abbrev */
  594.   if (nmatched < minchars)
  595.      return FALSE;
  596.   return TRUE;            /* A-OK */
  597. }
  598.  
  599.  
  600.  
  601. /*
  602.  * parses one line of the response file or command line options
  603.  *
  604.  * return the last arguement parsed so that the outer program knows how
  605.  * many extra arguements were read (either 1 or 0)
  606.  *
  607.  * pass in argc which is the maximum number of arguements in the list
  608.  *  and start_arg which is the arguement number to start at
  609.  */
  610.  
  611. int parse_switches (decompress_info_ptr cinfo, int argc, char * argv[], int start_arg)
  612. {
  613. int argn, c, i, on_flag;
  614. char * arg, * chr;
  615.  
  616. argn = start_arg;
  617.  
  618. on_flag = 0;
  619. arg = argv[argn];
  620.  
  621. if (*arg == ';') return argn;    /* this is a comment line ie do nothing */
  622.  
  623. /* test if we have a file name for viewing or path & mask (without the -path)
  624.  * as opposed to an option
  625.  */
  626. if (*arg != '-' && *arg != '+'){
  627.     if (strchr(arg, '\\') != NULL){        /* we have a directory if there is a backslash */
  628.         parse_path(arg);
  629.         return argn;
  630.         }
  631.     if (config_found == 0){
  632.         prep_for_exit();
  633.         printf("\nYou must run vidsetup before you can use dvpeg\n");
  634.         exit(-1);
  635.         }
  636.     c = view_defaults;
  637.     view_defaults &= (~ask_size_bit);    /* turn off second menu */
  638.     show_it(cinfo, arg);                /* show and wait for keypress */
  639.     view_defaults = c;
  640.     }
  641. else{
  642.     if (*arg++ == '+') on_flag = 1;  /*    arg++;    /* advance past switch marker character */
  643.  
  644.     if (keymatch(arg, "clscreen", 3)){
  645.         setup_text_screen();
  646.         init_screen();
  647.         }
  648.  
  649.     else if (keymatch(arg, "notext", 3)){
  650.         defaults &= (~no_text);
  651.         if (on_flag) defaults |= no_text;
  652.         }
  653.  
  654.     else if (keymatch(arg, "name", 3)){
  655.         defaults &= (~show_text);
  656.         picture_text_arguement[0] = 0;
  657.         if (on_flag){
  658.             defaults |= show_text;
  659.             if (++argn < argc)
  660.                 if (*argv[argn] == '*')
  661.                     strcpy(picture_text_arguement, argv[argn] + 1);
  662.                 else
  663.                     argn--;
  664.             }
  665.         }
  666.  
  667.     else if (keymatch(arg, "title", 3)){
  668.         defaults &= (~show_title);
  669.         picture_title_arguement[0] = 0;
  670.         if (on_flag){
  671.             defaults |= show_title;
  672.             if (++argn < argc)
  673.                 if (*argv[argn] == '*')
  674.                     strcpy(picture_title_arguement, argv[argn] + 1);
  675.                 else
  676.                     argn--;
  677.             }
  678.         }
  679.  
  680.     else if (keymatch(arg, "tree", 3)){
  681.         if (on_flag)
  682.             defaults |= show_tree;
  683.         else
  684.             defaults &= (~show_tree);
  685.         }
  686.  
  687.     else if (keymatch(arg, "drives", 3)){
  688.         if (on_flag)
  689.             defaults |= show_drives;
  690.         else
  691.             defaults &= (~show_drives);
  692.         }
  693.  
  694.     else if (keymatch(arg, "fifty", 3)){
  695.         if (on_flag)
  696.             view_defaults |= fifty_line_text;
  697.         else
  698.             view_defaults &= (~fifty_line_text);
  699.         }
  700.  
  701.     else if (keymatch(arg, "clgr", 3)){
  702.         if (on_flag)
  703.             defaults |= clear_before_draw;
  704.         else
  705.             defaults &= (~clear_before_draw);
  706.         }
  707.  
  708.     else if (keymatch(arg, "usefiles", 3)){
  709.         if (on_flag)
  710.             defaults |= dont_get_files;
  711.         else
  712.             defaults &= (~dont_get_files);
  713.         }
  714.  
  715. /*        view_defaults ^= ascending_bit;
  716.         defaults ^= error_msg_on;
  717.         defaults ^= use_default_file;
  718.         view_defaults ^= only_hi_color;
  719.         view_defaults ^= not_less_hi_color;
  720.     lock_during_pan
  721.     clear_during_pan .....  lots more
  722. */
  723.  
  724.     else if (keymatch(arg, "long", 3)){
  725.         if (on_flag)
  726.             defaults |= long_file_format;
  727.         else
  728.             defaults &= (~long_file_format);
  729.         }
  730.  
  731.     else if (keymatch(arg, "delay", 3)){
  732.         if (++argn < argc)
  733.             sscanf(argv[argn], "%d", &slideshow_pause);
  734.         }
  735.  
  736.     else if (keymatch(arg, "keypress", 3))
  737.         getch();
  738.  
  739.     else if (keymatch(arg, "config", 3)){
  740.         if (++argn < argc)    /* advance to next argument & check for error */
  741.             config_found |= load_config_viewer(argv[argn]);
  742.         }
  743.  
  744.     else if (keymatch(arg, "exit", 3)){
  745.         prep_for_exit();
  746.         exit(0);
  747.         }
  748.  
  749.     else if (keymatch(arg, "grayscale", 3)){
  750.         view_defaults &= (~grey_bit);
  751.         if (on_flag) view_defaults |= grey_bit;
  752.         }
  753.  
  754.     else if (keymatch(arg, "quantize", 3)){
  755.         view_defaults &= (~quantize_bit);
  756.         if (on_flag) view_defaults |= quantize_bit;
  757.         }
  758.  
  759.     else if (keymatch(arg, "dithering", 3)){
  760.         view_defaults &= ~(dithering_bit);
  761.         if (on_flag) view_defaults |= dithering_bit;
  762.         }
  763.  
  764.     else if (keymatch(arg, "controls", 3)){
  765.         do_slide_show = 0;
  766.         if (on_flag) do_slide_show = 1;
  767.         }
  768.  
  769.     else if (keymatch(arg, "lock", 3)){
  770.         mode_lock = -1;
  771.         if (on_flag)
  772.             if (++argn < argc){    /* advance to next argument & check for error */
  773.                 sscanf(argv[argn], "%d", &c);
  774.                 if (c > 0) mode_lock = c;
  775.                 }
  776.         }
  777.  
  778.     else if (keymatch(arg, "menu", 3)){
  779.         view_defaults &= (~ask_size_bit);    /* turn off second menu */
  780.         if (on_flag) view_defaults |= ask_size_bit;
  781.         }
  782.  
  783.     else if (keymatch(arg, "beep", 3)){
  784.         view_defaults &= (~beep_on);
  785.         if (on_flag) view_defaults ^= beep_on;
  786.         }
  787.  
  788.     else if (keymatch(arg, "mask", 3)){
  789.         if (on_flag){
  790.             for (c = 0; (c < max_file_masks) && (file_masks[c][0] != 0); c++) {}
  791.             if (c >= max_file_masks) c = 0;
  792.             if (++argn < argc)
  793.                 strcpy(file_masks[c], argv[argn]);        /* if wildcard is given use it */
  794.             }
  795.         else
  796.             for (c = 0; c < max_file_masks; c++)
  797.                 file_masks[c][0] = 0;        /* clear all other file masks */
  798.         }
  799.  
  800.     else if (keymatch(arg, "shrink", 3)){
  801.         if (!on_flag)
  802.             defaults &= ~shrink_enable_flag;    /* turn off if set to 0 */
  803.         else{
  804.             defaults |= shrink_enable_flag;
  805.             if (++argn < argc){
  806.                 shrink = *argv[argn] - '0';
  807.                 if (shrink == 0)
  808.                     view_defaults &= (~lock_shrink);
  809.                 else
  810.                     view_defaults |= lock_shrink;
  811.                 if (shrink > max_shrink) shrink = max_shrink;
  812.                 if (shrink < 1) shrink = 1;
  813.                 if (view_defaults & lock_shrink) lock_shrink_value = shrink;
  814.                 }
  815.             }
  816.         }
  817.  
  818.     else if (keymatch(arg, "panning", 3)){
  819.         view_defaults &= (~panning_bit);
  820.         if (on_flag) view_defaults |= panning_bit;
  821.         }
  822.  
  823.     else if (keymatch(arg, "slideshow", 3)){
  824.         if (file_info_head != NULL)
  825.             slide_show(cinfo);
  826.             }
  827.  
  828.     else if (keymatch(arg, "nolist", 3)){
  829.         defaults &= ~show_drives;
  830.         defaults &= ~show_tree;
  831.         defaults |= no_file_list;
  832.         }
  833.  
  834.     else if (keymatch(arg, "continous", 3))
  835.         defaults |= slide_show_continous;
  836.  
  837.     else if (keymatch(arg, "initshow", 3))
  838.         init_file_struct();
  839.  
  840.     else if (keymatch(arg, "addslide", 3)){
  841.         /* first find the highest number in the slideshow by searching the list */
  842.         if (++argn < argc){
  843.             c = 0;
  844.             if (file_info_head != NULL){        /* only do this if the memory has been alloced */
  845.                 for (i = max_file_records-1; i >= 0; i--)
  846.                     if ((file_info_head + i)->slide_num > c)
  847.                         c = (file_info_head +i)->slide_num;
  848.  
  849.                 number_files += insert_in_place(argv[argn], 10, 0, NONE, 0, c+1);
  850.                 }
  851.             }
  852.         }
  853.     else if (keymatch(arg, "path", 3))
  854.         if (++argn < argc)
  855.             parse_path(argv[argn]);
  856.     }
  857. return argn;            /* return index of next arg (file name) */
  858. }
  859.  
  860.  
  861.  
  862. /*
  863.  * parse a string which contains the file path
  864.  *  and update the path to the pictures
  865.  * -if there are wildcards at the end; assume that a file mask has
  866.  *  been given and erase the current one & add new mask
  867.  *
  868.  * assume either ..<path> or \\<path> or d:\<path> or path to append
  869.     the path is optional in any of the first 3 options
  870.  */
  871.  
  872. void parse_path(char * arg)
  873. {
  874. char * chr;
  875. int c;
  876.  
  877. if (strlen(arg) > 1){
  878.     switch(*(arg+1)){
  879.         case '.':        /* hop back one level in the path */
  880.             arg += 2;        /* get past it */
  881.             chr = file_path + strlen(file_path) - 2;    /* point to last char - don't forget extra \ at the end */
  882.             if (strchr(file_path, '\\') != NULL){
  883.                 while (*chr-- != '\\') {}
  884.                 *(chr + 1) = 0;        /* lop off the last path leaf */
  885.                 }
  886.             break;
  887.         case '\\':        /* hop to root but keep drive letter */
  888.             file_path[3] = 0;
  889.             arg += 2;
  890.             break;
  891.         case ':':        /* a drive has been given */
  892.             strncpy(file_path, arg, 1);    /* assume first letter is the drive */
  893.             file_path[1] = 0;
  894.             strcat(file_path, ":\\");
  895.             arg += 2;
  896.             if (*arg == '\\') arg++;
  897.             break;
  898.         }
  899.     /* now if anything is left it is a file mask or the last of the path without the terminating \ char */
  900.     if (strchr(arg, '?') == NULL && strchr(arg, '*') == NULL)
  901.         strcat(file_path, arg);
  902.     else{        /* we have a path */
  903.         for (c = 1; c < max_file_masks; c++)
  904.             file_masks[c][0] = 0;        /* clear all other file masks */
  905.         strcpy(file_masks[0], arg);        /* if wildcard is given use it */
  906.         }
  907.     }
  908. }
  909.  
  910.  
  911.  
  912. /*
  913.  * do a slideshow from the file list
  914.  * - handle continous show (if flag is set)
  915.  *
  916.  */
  917.  
  918. void slide_show(decompress_info_ptr cinfo)
  919. {
  920. int current_slide_num;        /* slide show vars */
  921. char temp_char[50];
  922. int c, i;        /* general purpose vars */
  923.  
  924. current_slide_num = 1;    /* init to showing first selected file */
  925. key_hit = 0;                /* flag for a non ESC key being hit while doing a slide show */
  926. time_at_start = 0;        /* setup delay timer */
  927. do_slide_show = 1;
  928.  
  929. /* verify that 1 selection exists */
  930. /* i is the slide show index, from the top down */
  931. i = max_file_records-1;
  932. show_next_file = 0;
  933.  
  934. while(i >= 0 && show_next_file == 0){
  935.     if ((file_info_head + i)->slide_num == 1)    /* find first file */
  936.         show_next_file = 1;
  937.     else
  938.         i--;
  939.     }
  940.  
  941. c = view_defaults;
  942. view_defaults &= (~ask_size_bit);    /* turn off second menu */
  943. view_defaults &= (~panning_bit);        /* turn off panning */
  944.  
  945. while (show_next_file != 0 && key_hit == 0){
  946.     if (i >= 0){
  947.         _fstrcpy(temp_char, (file_info_head + i)->name);
  948.         show_it(cinfo, temp_char);
  949.         if (key_hit == 0)        /* only do this if no key was hit - ie an immediate exit requested */
  950.             time_at_start = time(NULL);        /* reset delay timer */
  951.         else
  952.             time_at_start = 0;
  953.         current_slide_num++;                /* inc so that we get the next file the next time */
  954.         }
  955.  
  956.     /* find next selection */
  957.     for (i = max_file_records-1; (i >= 0) && (file_info_head + i)->slide_num != current_slide_num; i--){}
  958.  
  959.     /* end the show or do continous loop ??? */
  960.     if (i >= 0)
  961.         show_next_file = 1;
  962.     else
  963.         if (defaults & slide_show_continous){    /* continous show ?? -> find first picture */
  964.             current_slide_num = 1;
  965.             i = max_file_records - 1;
  966.             while((file_info_head + i)->slide_num != 1 && (i >= 0)) i--;
  967.             show_next_file = 1;
  968.             }
  969.         else{
  970.             getch();        /* last pic so delay for keypress */
  971.             show_next_file = 0;
  972.             }
  973.     }
  974.  
  975. defaults &= ~slide_show_continous;        /* always clear this upon exit */
  976. view_defaults = c;    /* restore ask_size_bit */
  977. do_slide_show = 0;
  978. }
  979.  
  980.  
  981.  
  982.  
  983. /*
  984.  * clear the (edited) user list of chosen video modes
  985.  */
  986.  
  987. void clear_list(void)
  988. {
  989. int c;
  990. for (c = 0; c < number_modes_in_list; c++)
  991.     ok_mode[c] = -1;                        /* signal as unused to ensure undefined modes are not used */
  992. }
  993.  
  994.  
  995.  
  996.  
  997.  
  998. /*
  999.  * check to see if there should be a pause before showing pic
  1000.  * if it is > 2 min. then assume something is wrong and return
  1001.  */
  1002.  
  1003. void pause_for_slideshow(void)
  1004. {
  1005. unsigned delay_in_sec;
  1006.  
  1007. if (do_slide_show){
  1008.     delay_in_sec = time(NULL) - time_at_start;
  1009.     if (delay_in_sec > 120) return;
  1010.     if (delay_in_sec < slideshow_pause)
  1011.         delay((slideshow_pause - delay_in_sec) * 1000);
  1012.     }
  1013. }
  1014.  
  1015.  
  1016.  
  1017. /*
  1018.  * setup the selected video mode
  1019.  */
  1020.  
  1021. void set_video(int mode_index)
  1022. {
  1023. if (current_graphics_mode != mode_index){        /* first check to see if we are still in the graphics mode */
  1024.     current_graphics_mode = mode_index;
  1025.     forcevga(video_cards[mode_index].card_number);
  1026.     svgamode(video_cards[mode_index].set_ax,
  1027.             video_cards[mode_index].set_bx,
  1028.             video_cards[mode_index].x_width,
  1029.             video_cards[mode_index].card_number);
  1030.  
  1031.     /* set up screen limits */
  1032.  
  1033.     x_max = video_cards[mode_index].x_size;
  1034.     y_max = video_cards[mode_index].y_size;
  1035.     maxy = video_cards[mode_index].y_size;
  1036.  
  1037.     if (defaults & clear_before_draw)        /* clear 16 * 64k banks of memory ie 1M */
  1038.         clear_video_memory(16);
  1039.     }
  1040. else
  1041.     clear_video_memory(16);        /* clear 1 Mbyte */
  1042.  
  1043. video_resolution = video_cards[mode_index].resolution;        /* update this for everything else */
  1044. setup_image_info();        /* setup all panning, tint info */
  1045. }
  1046.  
  1047.  
  1048.  
  1049. /*
  1050.  * To accept the image data from decompression, you must define four routines
  1051.  * output_init, put_color_map, put_pixel_rows, and output_term.
  1052.  *
  1053.  * You must understand the distinction between full color output mode
  1054.  * (N independent color components) and colormapped output mode (a single
  1055.  * output component representing an index into a color map).  You should use
  1056.  * colormapped mode to write to a colormapped display screen or output file.
  1057.  * Colormapped mode is also useful for reducing grayscale output to a small
  1058.  * number of gray levels: when using the 1-pass quantizer on grayscale data,
  1059.  * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
  1060.  * can regard the indexes are directly representing gray levels at reduced
  1061.  * precision.  In any other case, you should not depend on the colormap
  1062.  * entries having any particular order.
  1063.  * To get colormapped output, set cinfo->quantize_colors to TRUE and set
  1064.  * cinfo->desired_number_of_colors to the maximum number of entries in the
  1065.  * colormap.  This can be done either in your main routine or in
  1066.  * d_ui_method_selection.  For grayscale quantization, also set
  1067.  * cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
  1068.  * (presently this is the default, but it may not be so in the future).
  1069.  *
  1070.  * The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
  1071.  * useful examples of what these routines should actually do, although each of
  1072.  * them is encrusted with a lot of specialized code for its own file format.
  1073.  */
  1074.  
  1075.  
  1076. METHODDEF void
  1077. output_init (decompress_info_ptr cinfo)
  1078. /* This routine should do any setup required */
  1079. {
  1080.  
  1081.   /* This routine can initialize for output based on the data passed in cinfo.
  1082.     * Useful fields include:
  1083.     *    image_width, image_height    Pretty obvious, I hope.
  1084.     *    data_precision            bits per pixel value; typically 8.
  1085.     *    out_color_space            output colorspace previously requested
  1086.     *    color_out_comps            number of color components in same
  1087.     *    final_out_comps            number of components actually output
  1088.     * final_out_comps is 1 if quantize_colors is true, else it is equal to
  1089.     * color_out_comps.
  1090.     *
  1091.     * If you have requested color quantization, the colormap is NOT yet set.
  1092.     * You may wish to defer output initialization until put_color_map is called.
  1093.     */
  1094. int i;
  1095.  
  1096. check_keybd(cinfo, "");
  1097.  
  1098. /* if this then it is a grayscale without quantizing
  1099.  * but don't choke if there is no colormap, quantized grayscale (ie 16 color) will get here
  1100.  * and not have a colormap made
  1101.  */
  1102.  
  1103. if (cinfo->colormap != NULL){        /* is there a colormap; only JPEG quantized will not have one at this point */
  1104.     if (video_resolution == VGA)        /* only 16 color pallet ?? */
  1105.         quantize_colormap(cinfo);
  1106.  
  1107.     if (cinfo->out_color_space == CS_GRAYSCALE)
  1108.         for (i=0; i < 256; i++)
  1109.             palbuf[i][0] = palbuf[i][1] = palbuf[i][2] = GETJSAMPLE(cinfo->colormap[0][i]);
  1110.     }
  1111.  
  1112. if (cinfo->quantize_colors == FALSE){    /* this is only for non quantized JPEGs */
  1113.     pause_for_slideshow();
  1114.     set_video(video_mode_used);
  1115.     if (video_resolution <= SVGA)        /* if non-quantized JPEG then init the "faked" pallet */
  1116.         setup_pallet();
  1117.     writeText(text_line_x, text_line_y, picture_text);
  1118.     }
  1119. }
  1120.  
  1121.  
  1122.  
  1123. /*
  1124.  * This routine is called if and only if you have set cinfo->quantize_colors
  1125.  * to TRUE.  It is given the selected colormap and can complete any required
  1126.  * initialization.  This call will occur after output_init and before any
  1127.  * calls to put_pixel_rows.  Note that the colormap pointer is also placed
  1128.  * in a cinfo field, whence it can be used by put_pixel_rows or output_term.
  1129.  * num_colors will be less than or equal to desired_number_of_colors.
  1130.  *
  1131.  * The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
  1132.  *        JSAMPLE colormap[component][indexvalue]
  1133.  * where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
  1134.  * runs from 0 to num_colors-1.  Note that this is actually an array of
  1135.  * pointers to arrays rather than a true 2D array, since C does not support
  1136.  * variable-size multidimensional arrays.
  1137.  * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  1138.  * to be as portable as the JPEG code proper, you should always access JSAMPLE
  1139.  * values with the GETJSAMPLE() macro, which will do the right thing if the
  1140.  * machine has only signed chars.
  1141.  */
  1142.  
  1143. METHODDEF void
  1144. put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  1145. {
  1146. int i;
  1147. /* remember it only gets here if it is 256 color output not for 15 or 24 bit modes */
  1148.  
  1149. number_pallet_colors = num_colors;
  1150. if (colormap != NULL){
  1151.     if (cinfo->quantize_colors == TRUE){        /* removed test for color_space = CS_RGB */
  1152.         if (cinfo->out_color_space == CS_RGB)
  1153.             for (i = 0; i < num_colors; i++){
  1154.                 palbuf[i][0] = GETJSAMPLE(colormap[0][i]);
  1155.                 palbuf[i][1] = GETJSAMPLE(colormap[1][i]);
  1156.                 palbuf[i][2] = GETJSAMPLE(colormap[2][i]);
  1157.                 }
  1158.         else{
  1159.             /* this is quantized grayscale; it is either 256 shades or maps 256 shades to 16; so we must fill all 256
  1160.              *  currently this is only used by quantized to 16 shades
  1161.              */
  1162.             if (cinfo->quantize_colors == TRUE)        /* this is only for quantized JPEGs */
  1163.                 for (i=0; i < num_colors; i++)
  1164.                     palbuf[i][0] = palbuf[i][1] = palbuf[i][2] = GETJSAMPLE(colormap[0][i]);
  1165.             }
  1166.         pause_for_slideshow();
  1167.         set_video(video_mode_used);
  1168.         setup_pallet();
  1169.         writeText(text_line_x, text_line_y, picture_text);
  1170.         }
  1171.     }
  1172. else        /* last chance to set the color map - message if we don't have one */
  1173.     ERREXIT(cinfo->emethods, "color map pointer is NULL");
  1174. }
  1175.  
  1176.  
  1177.  
  1178. /*
  1179.  * remap the 256 color pallet to a 16 grayscale
  1180.  *  or provide a 1 to 1 mapping for 256 to 256 (ie all other picture types)
  1181.  *
  1182.  * do this by remapping the color map so that it points to the first 16 colors for 16 color modes
  1183.  * This is done with the remap[] array with 0..255 input and 0..15 output
  1184.  * First generate the mapping function then replace the colormap with a graduated grayscale
  1185.  *
  1186.  * assume storage is setup (should be) for remap[][]
  1187.  */
  1188.  
  1189. void quantize_colormap(decompress_info_ptr cinfo)
  1190. {
  1191. unsigned int i, j;
  1192. unsigned long brightness;    /* scaled value 0 .. 15 */
  1193. JSAMPARRAY colormap;
  1194.  
  1195. colormap = cinfo->colormap;
  1196.  
  1197. for (i = 0; i < 256; i++){
  1198.     j = i << 4;        /* this fixes the compiler problem -> without it bad code is generated */
  1199.  
  1200.     /* is the image single component, ie gray?  This is tested differently for JPEGs and others */
  1201.  
  1202.     if ((type_of_picture != JPG && cinfo->num_components == 1) ||
  1203.         (type_of_picture == JPG && cinfo->quantize_colors == FALSE))
  1204.         brightness = (unsigned long)colormap[0][i] >> 4;
  1205.     else
  1206.         brightness = ((unsigned long)colormap[0][i] * 30 +
  1207.             (unsigned long)colormap[1][i] * 59 +
  1208.             (unsigned long)colormap[2][i] * 11) / 1594;
  1209.     remap[0][i] = (unsigned char) brightness;
  1210.     colormap[0][i] = (unsigned char) j + 8;    /* ie in first 16 colors run 0 .. full brightness */
  1211.     }
  1212. }
  1213.  
  1214.  
  1215.  
  1216. /*
  1217.  * if given a 3 component (R,G,B) or 1 componet (greyscale), and >> 256 color image fake a colormap
  1218.  *  - set the colormap to a greyscale fade and use the first component (grey or Red) as an index
  1219.  *  - if the colormap is only 16 colors then use the colormap to map 256 shades to 16 shades
  1220.  *     ie reading in 256 shade Targa and convert to a 16 shade display
  1221.  */
  1222.  
  1223. void fake_colormap(decompress_info_ptr cinfo, JSAMPARRAY cmap, int num_colors)
  1224. {
  1225. int i;
  1226.  
  1227. /* Allocate space to store the colormap, 256 bytes * 3 rows */
  1228. cmap = (*cinfo->emethods->alloc_small_sarray) ((long) 256, 3);
  1229. cinfo->colormap = cmap;
  1230.  
  1231. for (i = 0; i < 256; i++)
  1232.     cmap[0][i] = i;
  1233.  
  1234. /* now fake the darn S/W */
  1235.  
  1236. cinfo->out_color_space = CS_GRAYSCALE;        /* this forces the color-map writing routine to only use the first component of the colormap to generate greyscale */
  1237. cinfo->color_map_present = TRUE;
  1238. cinfo->actual_number_of_colors = num_colors;
  1239. }
  1240.  
  1241.  
  1242.  
  1243.  
  1244. /*
  1245.  * This routine gets control after the JPEG file header has been read;
  1246.  * at this point the image size and colorspace are known.
  1247.  * The routine must determine what output routines are to be used, and make
  1248.  * any decompression parameter changes that are desirable.  For example,
  1249.  * if it is found that the JPEG file is grayscale, you might want to do
  1250.  * things differently than if it is color.  You can also delay setting
  1251.  * quantize_colors and associated options until this point.
  1252.  *
  1253.  * j_d_defaults initializes out_color_space to CS_RGB.  If you want grayscale
  1254.  * output you should set out_color_space to CS_GRAYSCALE.  Note that you can
  1255.  * force grayscale output from a color JPEG file (though not vice versa).
  1256.  */
  1257.  
  1258. METHODDEF void
  1259. d_ui_method_selection (decompress_info_ptr cinfo)
  1260. {
  1261. static int
  1262.         i, temp,
  1263.         repaint,
  1264.         video_mode_pointed;    /* the video mode (index into ok_mode[] list currently selected */
  1265.  
  1266. /* setup important drawing info */
  1267.  
  1268. picture_x_size = cinfo->image_width;
  1269. picture_x_center = picture_x_size >> 1;
  1270. picture_y_size = cinfo->image_height;
  1271. picture_y_center = picture_y_size >> 1;
  1272.  
  1273. shrink = 1;
  1274.  
  1275. /* now check to see if we have the right H/W for the image
  1276.     ie a picture with >> 256 colors can not be displayed on SVGA
  1277.     -> if the picture has >> 256 colors fake a greyscale image for quick and dirty viewing
  1278.     */
  1279.  
  1280. /* if grayscale input, force grayscale output; */
  1281. /* else leave the output colorspace as set by main routine. */
  1282.   if (cinfo->jpeg_color_space == CS_GRAYSCALE)
  1283.      cinfo->out_color_space = CS_GRAYSCALE;
  1284.  
  1285. #ifdef small_viewer        /* if it is small we only support non quantized grayscale */
  1286. cinfo->out_color_space = CS_GRAYSCALE;
  1287. #endif
  1288.  
  1289.   /* select output routines */
  1290.   cinfo->methods->output_init = output_init;
  1291.   cinfo->methods->put_color_map = put_color_map;
  1292.   cinfo->methods->output_term = output_term;
  1293.  
  1294.  
  1295. make_mode_list(cinfo);
  1296.  
  1297. /*    - first find good window size */
  1298.  
  1299. video_mode_pointed = pick_screen_mode();
  1300. video_mode_used = ok_mode[video_mode_pointed];
  1301.  
  1302. /* setup enable pan because the user may have the menu turned off */
  1303. autocheck_panning(video_mode_used);
  1304. autocheck_shrinking(video_mode_used);
  1305.  
  1306. video_mode_pointed = pick_screen_mode();
  1307. video_mode_used = ok_mode[video_mode_pointed];
  1308.  
  1309. repaint = 1;
  1310. i = 0;
  1311.  
  1312. /*
  1313.  * make sure we do this once if asked for
  1314.  *
  1315.  * this loop is only entered if the menu is being shown
  1316.  */
  1317.  
  1318.  
  1319. while ( (i != RTN) && (view_defaults & ask_size_bit)){
  1320.  
  1321. /* only clear and repaint if absolutely necessary - ie avoid the flicker */
  1322.     if (repaint){
  1323.         open_window(preview_win_x, preview_win_y);
  1324.  
  1325.         gotoxy(1,1);
  1326.         textcolor(WHITE);
  1327.         cprintf("File: %10s, %4i * %4i, ", file_being_viewed, picture_x_size, picture_y_size);
  1328.         repaint = 0;
  1329.         if (cinfo->out_color_space == CS_RGB)
  1330.             cprintf("color");
  1331.         else
  1332.             cprintf("greyscale");
  1333.         if (type_of_picture == JPG)
  1334.             switch (jpeg_type){
  1335.                 case H2V2:
  1336.                     cprintf(", h2v2");
  1337.                     break;
  1338.                 case H2V1:
  1339.                     cprintf(", h2v1");
  1340.                     break;
  1341.                 case H1V1:
  1342.                     cprintf(", h1v1");
  1343.                 }
  1344.  
  1345.         if (picture_description[0] != 0){
  1346.             textcolor(LIGHTGREEN);
  1347.             picture_description[file_name_len - 1] = 0;    /* limit length */
  1348.             if ((preview_win_x - 4) < file_name_len)
  1349.                 picture_description[preview_win_x - 4] = 0;    /* limit length */
  1350.             cprintf("\r\n%-s\r\n", picture_description);
  1351.             textcolor(WHITE);
  1352.             }
  1353.         }
  1354.  
  1355.     autocheck_panning(video_mode_used);
  1356.  
  1357.     gotoxy(1,3);
  1358.  
  1359. #ifndef small_viewer
  1360.     show_defaults(0, type_of_picture == JPG);
  1361. #endif
  1362.  
  1363.     cprintf("\r\nVideo modes (K ");
  1364.     if (mode_lock >= 0) cprintf("unlocks):\r\n");
  1365.     else cprintf("locks):  \r\n");
  1366.  
  1367.     for (i=0; i < number_modes_in_list; i++){
  1368.         temp = ok_mode[i];
  1369.         if (temp >= 0){
  1370.             if (temp == video_mode_used && mode_lock < 0)
  1371.                 textcolor(LIGHTMAGENTA);
  1372.             else
  1373.                 textcolor(LIGHTGRAY);
  1374.             if (video_cards[temp].y_size == mode_lock)
  1375.                 textcolor(LIGHTRED);
  1376.  
  1377.             cprintf("     %15s    %4i   %5i %10s\r\n",video_card_names[video_cards[temp].card_number],
  1378.                 video_cards[temp].x_size, video_cards[temp].y_size,
  1379.                 card_type[video_cards[temp].resolution]);
  1380.             textcolor(WHITE);
  1381.             }
  1382.         }
  1383.     switch( (i = get_key()) ){
  1384.         case escape:
  1385.                 error_exit("");
  1386.                 break;
  1387. #ifndef small_viewer
  1388.         case F1:
  1389.                 clrscr();
  1390.                 cprintf("up/down arrow - select a video mode\r\n");
  1391.                 cprintf("enter - check out that picture\r\n");
  1392.                 cprintf("escape - exit\r\n");
  1393.                 cprintf("P - Panning\r\n");
  1394.                 cprintf("S - adjust Shrinking\r\n");
  1395.                 cprintf("D - Dithering\r\n");
  1396.                 cprintf("G - Grayscale colorspace\r\n");
  1397.                 cprintf("Q - one / two pass Quantizer\r\n");
  1398.                 cprintf("M - this menu on/off\r\n");
  1399.                 cprintf("E - End of pic. beep\r\n");
  1400.                 cprintf("K - lock a video mode\r\n");
  1401.                 if (any_hi_color)
  1402.                     cprintf("L - Lockout of SVGA modes for jpegs\r\n");
  1403.                 getch();
  1404.                 repaint = 1;
  1405.                 break;
  1406. #endif
  1407.         case arrow_up:
  1408.                 do{                /* make sure that we get an existing mode */
  1409.                     if (video_mode_pointed > 0) video_mode_pointed -=1;
  1410.                     else video_mode_pointed = number_modes_in_list - 1;
  1411.                     } while (ok_mode[video_mode_pointed] == -1);
  1412.                 break;
  1413.         case arrow_down:
  1414.                 do{
  1415.                     if (video_mode_pointed < number_modes_in_list - 1) video_mode_pointed += 1;
  1416.                     else video_mode_pointed = 0;
  1417.                     } while (ok_mode[video_mode_pointed] == -1);
  1418.                 break;
  1419.         case 'K':
  1420.         case 'k':        /* lock the video mode that is selected */
  1421.                 if (mode_lock >= 0)
  1422.                     mode_lock = -1;    /* reset ie toggle it */
  1423.                 else
  1424.                     mode_lock = video_cards[video_mode_used].y_size;
  1425.                 break;
  1426.         case RTN:        /* do nothing */
  1427.                 break;
  1428.         default:
  1429.  
  1430. #ifndef small_viewer
  1431.                 repaint = change_defaults(i, 0);
  1432. #endif
  1433.                 if (repaint > 1){
  1434.                     repaint = 1;
  1435.                     if (view_defaults & lock_shrink == 0);
  1436.                         shrink = 1;
  1437.                     make_mode_list(cinfo);    /* update list and repaint */
  1438.                     video_mode_pointed = pick_screen_mode();
  1439.                     video_mode_used = ok_mode[video_mode_pointed];
  1440.                     autocheck_shrinking(video_mode_used);
  1441.                     }
  1442.             }
  1443.     video_mode_used = ok_mode[video_mode_pointed];
  1444.     }        /* finally the close of that while */
  1445.  
  1446. if (mode_lock >= 0){
  1447.     /* if the mode lock is being used then the Y resolution has been selected and we have to
  1448.         find a video mode that matches that resolution.  Ideally there is only one mode of that
  1449.         size so we just have to do a single pass of the table and grab the first one */
  1450.     for (i=0; i < number_modes_in_list; i++){
  1451.         temp = ok_mode[i];
  1452.         if (temp >= 0)
  1453.             if (video_cards[temp].y_size == mode_lock)
  1454.                 video_mode_used = temp;
  1455.         }
  1456.     }
  1457.  
  1458. video_display_resolution = 0xff;        /* assume 8 bit display -> this tweaks the IJG JPEG code for grayscale viewing dithering for non 8 bit displays */
  1459.  
  1460. /* default conditions */
  1461. cinfo -> quantize_colors = FALSE;
  1462. cinfo -> two_pass_quantize = FALSE;
  1463.  
  1464. cinfo->use_dithering = view_defaults & dithering_bit;
  1465. cinfo->do_block_smoothing = view_defaults & smoothing_bit;
  1466.  
  1467. if (view_defaults & grey_bit != 0 && type_of_picture == JPG)
  1468.     cinfo->out_color_space = CS_GRAYSCALE;
  1469.  
  1470. video_resolution = video_cards[video_mode_used].resolution;
  1471.  
  1472. setup_image_info();        /* setup all drawing parameters */
  1473.  
  1474. if (enable_pan)        /* adjust storage for line or full buffering - only for 15/16 bit modes */
  1475.     i = picture_y_size;
  1476. else
  1477.     i = 1;
  1478. raw_pic_ptr = (*cinfo->emethods->request_big_sarray) (picture_x_size * bytes_per_pixel , i, 1L);
  1479.  
  1480. /* pick a different putting routine for hi_color vs VGA ie for speed */
  1481. switch (video_resolution){
  1482.     case VGA:        /* always quantize if JPEG, always grayscale, always rig color map */
  1483.         cinfo->methods->put_pixel_rows = put_pixel_rows;
  1484. #ifndef small_viewer        /* don't want color for reduced version since there is no quantizer */
  1485. #if 0
  1486.         if (more_defaults & slow_gray){
  1487.             cinfo->quantize_colors = TRUE;
  1488.             cinfo->desired_number_of_colors = 16;
  1489.             }
  1490.         if (type_of_picture == JPG && (more_defaults & vga_as_color)){
  1491.             cinfo->out_color_space = CS_RGB;
  1492.             cinfo->two_pass_quantize = view_defaults & quantize_bit;
  1493.             }
  1494.         else
  1495. #endif
  1496.         if (type_of_picture == JPG && (cinfo->out_color_space != CS_GRAYSCALE)){
  1497.             cinfo->out_color_space = CS_RGB;
  1498.             cinfo->quantize_colors = TRUE;
  1499.             cinfo->desired_number_of_colors = 16;
  1500.             cinfo->two_pass_quantize = view_defaults & quantize_bit;
  1501.             }
  1502. #else
  1503.             cinfo->out_color_space = CS_GRAYSCALE;
  1504. #endif
  1505.  
  1506.         /* storage for remapping color pallet of any images ie 256 color -> 16 grayscale
  1507.          * must be intialized for all pallet drawing */
  1508.         remap = (*cinfo->emethods->alloc_small_sarray) ((long) 256, 3);
  1509.         for (i = 0; i < 256; i++)        /* default to no remapping */
  1510.             remap[0][i] = i;
  1511.  
  1512.         /* for JPEG we are going to have it generate the color map
  1513.          * for everything else the colormap maps from 8 bit input to 4 bit color
  1514.          */
  1515.         if (cinfo->color_map_present != 1 && cinfo->quantize_colors == FALSE)
  1516.             fake_colormap(cinfo, patch_colormap, 16);
  1517.         if (view_defaults & ask_size_bit && cinfo->color_map_present != TRUE)
  1518.             cprintf("quantizing down to 16 colors\r\n");
  1519.         break;
  1520.     case SVGA:
  1521. /* this was used to dither the 256 color (6 bit) display of grayscale
  1522.  * when quantizing - quantizing is no longer used for grayscale
  1523.         video_display_resolution = 0xfc;        /* 6 bit display */
  1524.         cinfo->methods->put_pixel_rows = put_pixel_rows;
  1525.         if (cinfo->out_color_space == CS_GRAYSCALE){
  1526.             if (type_of_picture == JPG)
  1527.                 fake_colormap(cinfo, patch_colormap, 256);
  1528.             }
  1529.         else{
  1530.             cinfo->quantize_colors = TRUE;
  1531.             cinfo->two_pass_quantize = view_defaults & quantize_bit;
  1532.             cinfo->desired_number_of_colors = 256;
  1533.             }
  1534.  
  1535.         /* if the image is non JPEG, and has no color map but must be shown on
  1536.             a 256 color mode then fake it */
  1537.         if (cinfo->color_map_present != 1 && type_of_picture != JPG)
  1538.             fake_colormap(cinfo, patch_colormap, 256);
  1539.  
  1540.         if (view_defaults & ask_size_bit && cinfo->color_map_present != TRUE)
  1541.             cprintf("quantizing down to 256 colors\r\n");
  1542.         break;
  1543.     case SVGA_15_bit:
  1544.     case SVGA_16_bit:
  1545.     case SVGA_24_bit:
  1546.         tint_table = (*cinfo->emethods->alloc_small_sarray) ((long) 256, 3);  /* table to speed up screen tinting */
  1547.         cinfo->methods->put_pixel_rows = put_hi_pixel;
  1548.         if (type_of_picture == JPG)
  1549.             cinfo->methods->put_pixel_rows = put_pixel_not;
  1550.         break;
  1551.     }
  1552.  
  1553. /* setup the row and column counters for shrinking images */
  1554. col_cntr = row_cntr = 1;
  1555. }
  1556.  
  1557.  
  1558.  
  1559.  
  1560. /*
  1561.  * selected the video mode that can hold all dimensions of the image
  1562.  * or default to the largest
  1563.  * fudge the size calculation by "twiddle_factor" pixels for those pics that are slightly bigger than the mode
  1564.  *  - return an index into ok_mode[]
  1565.  *
  1566.  *  - assume x_size, y_size, shrink are properly defined
  1567.  * if we have SVGA don't bother with VGA
  1568.  * if we have 15/16/24 bit, don't bother with VGA unless grayscale
  1569.  */
  1570.  
  1571. int pick_screen_mode(void)
  1572. {
  1573. int i, mode_picked, temp;
  1574. int    have_SVGA,            /* have SVGA modes */
  1575.     have_hiclr;            /* have hi-color modes */
  1576.  
  1577. have_SVGA = 0;
  1578. have_hiclr = 0;
  1579. for (i = 0; i < number_modes_in_list; i++)
  1580.     if (ok_mode[i] >= 0)        /* only bother if its a valid mode and not flaged as empty */
  1581.         switch (video_cards[ok_mode[i]].resolution){
  1582.             case SVGA:
  1583.                 have_SVGA = 1;
  1584.                 break;
  1585.             case SVGA_15_bit:
  1586.             case SVGA_16_bit:
  1587.             case SVGA_24_bit:
  1588.                 have_hiclr = 1;
  1589.             }
  1590.  
  1591. /* first if image is > all modes default to largest mode (not really the largest since the ordering is 4, 8, 15, 16, 24 bit) */
  1592. for (i = 0; i < number_modes_in_list; i++)
  1593.     if (ok_mode[i] >= 0) mode_picked = i;
  1594.  
  1595. for (i = number_modes_in_list - 1; i >=0; i--){
  1596.     temp = ok_mode[i];
  1597.     if (video_cards[temp].x_size >= picture_x_size / shrink - twiddle_factor
  1598.             && video_cards[temp].y_size >= picture_y_size / shrink - twiddle_factor
  1599.             &&    temp >= 0)
  1600.         switch(video_cards[temp].resolution){
  1601.             case VGA:
  1602.                 if (have_SVGA & have_hiclr == 0)
  1603.                     mode_picked = i;
  1604.                 break;
  1605.             case SVGA:
  1606.                 if (!have_hiclr)    /* case of grayscale JPEG is solved because the mode selection routine will only have picked 4,8 bit */
  1607.                     mode_picked = i;
  1608.                 break;
  1609.             default:
  1610.                 mode_picked = i;
  1611.             }
  1612.     }
  1613. return mode_picked;
  1614. }
  1615.  
  1616.  
  1617.  
  1618.  
  1619. /*
  1620.  * setup the enable_pan flag, shrink size
  1621.  *
  1622.  * only pan if the picture is larger than the screen
  1623.  *  unless edit_mode is set so that tint adjustments can be done and saved
  1624.  *
  1625.  */
  1626.  
  1627. void autocheck_panning(int mode_used)
  1628. {
  1629. enable_pan = 0;
  1630.  
  1631. if (view_defaults & always_pan){
  1632.     enable_pan = 1;
  1633.     return;
  1634.     }
  1635. enable_pan = view_defaults & panning_bit;
  1636.  
  1637. /* removed /shrink from the following calcs */
  1638. if (video_cards[mode_used].y_size >= picture_y_size - twiddle_factor
  1639.     && video_cards[mode_used].x_size >= picture_x_size - twiddle_factor)
  1640.         enable_pan = 0;
  1641. /* if the image is 24 bit full tinting can be done any time (no panning buffer rqd
  1642.  * if the image is 256 color the pallet is easily changed any time
  1643.  */
  1644. }
  1645.  
  1646.  
  1647.  
  1648.  
  1649. /*
  1650.  * setup the shrink size
  1651.  *
  1652.  * only pan if the picture is larger than the screen
  1653.  *  unless edit_mode is set so that tint adjustments can be done and saved
  1654.  *
  1655.  */
  1656.  
  1657. void autocheck_shrinking(int mode_used)
  1658. {
  1659. int i;
  1660.  
  1661. shrink = 1;        /* default to none */
  1662.  
  1663. if (view_defaults & lock_shrink){
  1664.     shrink =    lock_shrink_value;
  1665.     return;
  1666.     }
  1667.  
  1668. if (defaults & shrink_enable_flag){
  1669.     shrink = picture_y_size / video_cards[mode_used].y_size;
  1670.     if (picture_y_size % video_cards[mode_used].y_size > twiddle_factor) shrink++;
  1671.  
  1672.     i = picture_x_size / video_cards[mode_used].x_size;
  1673.     if (picture_x_size % video_cards[mode_used].x_size > twiddle_factor) i++;
  1674.  
  1675.     if (i > shrink) shrink = i;
  1676.     if (shrink > max_shrink) shrink = max_shrink;
  1677.     if (shrink < 1) shrink = 1;
  1678.     }
  1679. }
  1680.  
  1681.  
  1682.  
  1683.  
  1684. /*
  1685.  * 1) The video mode list is sorted in order of Y size
  1686.  * 2) pick the appropiate modes and sort them into order (ie low to hi)
  1687.  *  - only keep SVGA modes for GIF and hi_color for JPEGs
  1688.  *  - bomb if GIF and only hi_color modes and check to make sure that some
  1689.  *     hi_color modes exist for jpeg or else use SVGA for JPEG as a last resort
  1690.  */
  1691.  
  1692. void make_mode_list(decompress_info_ptr cinfo)
  1693. {
  1694. int i, mode_type,        /* index for loops */
  1695.     condition,
  1696.     lowest,                /* lowest resolution 15/16/24 bit mode */
  1697.     minimum;                /* include SVGA modes for color JPEG (ie mighty fast machine) */
  1698.  
  1699. clear_list();
  1700.  
  1701. /*
  1702.  * first check if we have a GIF (ie color_map present), If so keep only the SVGA modes
  1703.  * at this point we can also check to see if the image is grayscale
  1704.  *   -> if so color registers are better than everything but 24 bit
  1705.  * also keep all SVGA if there is nothing better (ie any_hi_color == 0
  1706.  */
  1707. if ( ((view_defaults & grey_bit) != 0 && type_of_picture == JPG) ||
  1708.         cinfo->color_map_present != 0 ||
  1709.         cinfo->out_color_space == CS_GRAYSCALE || any_hi_color == 0)
  1710.     {
  1711.     for (mode_type = SVGA; mode_type >= VGA; mode_type--)
  1712.         for (i = 0; i < number_modes_in_list; i++)
  1713.             if (all_modes[i] >= 0)        /* only bother if its a valid mode and not flaged as empty */
  1714.                 if (video_cards[all_modes[i]].resolution == mode_type)
  1715.                     insert_in_list(all_modes[i], 1);
  1716.  
  1717.     if (ok_mode[0] < 0)        /* if its gif and there are no SVGA modes bomb */
  1718.         ERREXIT(cinfo->emethods, "Need SVGA modes for GIFs");
  1719.     }
  1720. else{
  1721.     lowest = 9999;        /* nice high default larger than any video mode */
  1722.     condition = 0;        /* set if we want to lock out all SVGA modes less than the lowest hi-color mode */
  1723.     minimum = VGA;
  1724.     if (view_defaults & only_hi_color) minimum = SVGA + 1;
  1725.     if (view_defaults & not_less_hi_color) condition = 1;
  1726.  
  1727.     /* ok we can use non-pallet modes ==> keep everything but SVGA */
  1728.     for (mode_type = SVGA_24_bit; mode_type >= minimum; mode_type--)
  1729.         for (i = 0; i < number_modes_in_list; i++)
  1730.             if (all_modes[i] >= 0)        /* only bother if its a valid mode and not flaged as empty */
  1731.                 if (video_cards[all_modes[i]].resolution == mode_type){
  1732.                     if (mode_type > SVGA && video_cards[all_modes[i]].y_size < lowest) lowest = video_cards[all_modes[i]].y_size;
  1733.                     if (condition == 0 || video_cards[all_modes[i]].y_size > lowest || mode_type >> SVGA)
  1734.                         insert_in_list(all_modes[i], 1);
  1735.                     }
  1736.     }
  1737. }
  1738.  
  1739.  
  1740.  
  1741. /*
  1742.  * clear the file data record
  1743.  *
  1744.  * - alloc the memory if it is not setup, if still not enough memory start
  1745.  *   cutting down on the struct size
  1746.  * - 0 name (first byte) signifies empty
  1747.  * - 0 size indicates drive or directory tree
  1748.  */
  1749.  
  1750. void init_file_struct()
  1751. {
  1752. int i;
  1753.  
  1754. while ((file_info_head == NULL) && (max_file_records > 1)){
  1755.     file_info_head = (struct dir_info FAR *) farmalloc(sizeof(struct dir_info) * max_file_records);
  1756.     if (file_info_head == NULL){
  1757.         max_file_records >>= 1;
  1758.         if (max_file_records < 1) max_file_records = 1;
  1759.         }
  1760.     }
  1761.  
  1762. if (file_info_head != NULL)
  1763.     for (i = 0; i < max_file_records; i++){
  1764.         (file_info_head + i)->name[0] = 0;
  1765.         (file_info_head + i)->date = 0;
  1766.         (file_info_head + i)->size = 0;
  1767.         (file_info_head + i)->slide_num = 0;
  1768.         }
  1769. }
  1770.  
  1771.  
  1772.  
  1773. int test_position(char * f_name, long f_size, int f_date, int sorting_mode, struct dir_info FAR * info_ptr)
  1774. {
  1775. long difference;
  1776.  
  1777.         switch (sorting_mode){
  1778.             case FF_NAME:                /* case 0 sort by name */
  1779.                 difference = _fstricmp(f_name, (info_ptr)->name);
  1780.                 break;
  1781.             case FF_SIZE:                /* sort by file size */
  1782.                 difference = f_size - (info_ptr)->size;
  1783.                 break;
  1784.             case FF_DATE:                /* sort by date; year, month, then day; check for < 0 at each stage */
  1785.                 difference = (f_date & 0xfe) - ((info_ptr)->date & 0xfe);
  1786.                 if (difference != 0) break;
  1787.  
  1788.                 difference = (f_date & 0x1e) - ((info_ptr)->date & 0x1e);
  1789.                 if (difference != 0) break;
  1790.  
  1791.                 difference = (f_date & 0x1f) - ((info_ptr)->date & 0x1f);
  1792.                 break;
  1793.             case NONE:                /* in this case do nothing till the start of the list is found */
  1794.                 difference = 1;        /* one should find bottom of the list */
  1795.                 break;
  1796.             }
  1797.  
  1798. if (view_defaults & ascending_bit)
  1799.         difference = - difference;
  1800.  
  1801. /* if trying to move a directory entry then go up in the list */
  1802. if ((info_ptr)->size == 0){
  1803.     if (f_size != 0)
  1804.         difference = -1;        /* move up since we don't add onto a directory */
  1805.     }
  1806.  
  1807. if (difference > 0) return 1;
  1808. if (difference < 0) return -1;
  1809. else return 0;
  1810. }
  1811.  
  1812.  
  1813.  
  1814. /*
  1815.  * bisection search and insertion routine for list of files
  1816.  *
  1817.  * ffblk holds the value to be inserted
  1818.  *
  1819.  * usually you insert the directories first and sort by name
  1820.  * then add the other directory with any sort spec and the directories are fixed because:
  1821.  * if a size is 0 the object is fixed in place unless the new object is also 0 size - ie adding directories
  1822.  
  1823.  * start_index : lowest position to insert at (ie to stop the insert from disturbing the first items put in
  1824.  * return 1 if addition was done 0 if the list was full
  1825.  */
  1826.  
  1827. int insert_in_place(char * f_name, long f_size, int f_date, int sorting_mode, int start_index, int slide_position)
  1828. {
  1829. int top, bottom, delta, offset, index, difference;
  1830. struct dir_info FAR * info_ptr;
  1831.  
  1832. if (file_info_head == NULL) return 0;        /* no memory alloced for struct ! */
  1833.  
  1834. /* test to see if we are overwriting the last value ie inserting over the last item */
  1835. if ((file_info_head + max_file_records - 1)->name[0] != 0)
  1836.     return 0;        /* indicate nothing added */
  1837.  
  1838.  
  1839. top = max_file_records;
  1840. bottom = start_index;
  1841. delta = (top - bottom) >> 1;
  1842. offset = delta;
  1843. info_ptr = file_info_head + offset;
  1844. do{
  1845.     if ((info_ptr)->name[0] != 0){        /* its there is data */
  1846.         difference = test_position(f_name, f_size, f_date, sorting_mode, info_ptr);
  1847.         }
  1848.     else
  1849.         difference = 1;        /* move down the list since we are off the top.  ie no data is here */
  1850.  
  1851.     if (difference > 0)
  1852.         top -= delta;
  1853.     if (difference < 0)
  1854.         bottom += delta;
  1855.     delta = (top - bottom + 1) >> 1;
  1856.     offset = bottom + delta;
  1857.     info_ptr = file_info_head + offset;
  1858.     } while (delta > 0 && difference != 0);
  1859.  
  1860. /* now handle special case
  1861.  *  ie it went to the top of the list but backed down one because it was empty (ie odd number of searchs used)
  1862.  *     in this case we can just test where it is and see if its greater
  1863.  * - also special case: inserting the first item (check for 0 in info_ptr name
  1864.  */
  1865.  
  1866. if (test_position(f_name, f_size, f_date, sorting_mode, info_ptr) < 0 &&
  1867.         (info_ptr)->name[0] != 0){
  1868.     offset++;
  1869.     if (offset >= max_file_records) offset = max_file_records - 1;
  1870.     info_ptr = file_info_head + offset;
  1871.     }
  1872.  
  1873.  
  1874. _fmemmove(file_info_head + offset + 1, file_info_head + offset, (max_file_records - offset - 1) * sizeof(struct dir_info));
  1875.  
  1876. /*for (index = max_file_records - 1; index > offset; index--){
  1877.     _fstrcpy((file_info_head + index)->name, (file_info_head + index - 1)->name);
  1878.     (file_info_head + index)->size = (file_info_head + index - 1)->size;
  1879.     (file_info_head + index)->date = (file_info_head + index - 1)->date;
  1880.     }*/
  1881. _fstrcpy((info_ptr)->name, f_name);
  1882. (info_ptr)->size = f_size;
  1883. (info_ptr)->date = f_date;
  1884. (info_ptr)->slide_num = slide_position;
  1885.  
  1886. return 1;        /* indicate good addition to list */
  1887. }
  1888.  
  1889.  
  1890.  
  1891.  
  1892.  
  1893. /*
  1894.  * open the picture file,  check if its gif or jpeg
  1895.  *   setup the appropiate stuff for decoding each
  1896.  */
  1897.  
  1898. void check_file_in(decompress_info_ptr cinfo)
  1899. {
  1900. int c;
  1901.  
  1902. type_of_picture = JPG;    /* default */
  1903.  
  1904. if ((c = getc(cinfo->input_file)) == EOF)
  1905.     ERREXIT(cinfo->emethods, "Empty input file");
  1906.  
  1907. switch (c) {
  1908. #ifdef GIF_SUPPORTED
  1909.     case 'G':
  1910.         selrgif(cinfo);
  1911.         type_of_picture = GIF;
  1912.         break;
  1913. #endif
  1914.  
  1915. #ifdef PPM_SUPPORTED
  1916.     case 'P':
  1917.         j_sel_r_ppm(cinfo);
  1918.         type_of_picture = PPM;
  1919.         break;
  1920. #endif
  1921.  
  1922. #ifdef TARGA_SUPPORTED
  1923.     case 0x00:
  1924.         type_of_picture = TGA;
  1925.         j_sel_r_targa(cinfo);
  1926.         break;
  1927. #endif
  1928.     default:            /* assume default is jpeg type picture */
  1929.  
  1930. #ifdef JFIF_SUPPORTED
  1931.         jselrjfif(cinfo);
  1932. #else
  1933.         You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
  1934. #endif
  1935.         break;
  1936.     }
  1937.  
  1938. if (ungetc(c, cinfo->input_file) == EOF)
  1939.      ERREXIT(cinfo->emethods, "ungetc failed");
  1940. }
  1941.  
  1942.  
  1943.  
  1944. /*
  1945.  * file to read all non-jpeg images once the pointers have been setup
  1946.  */
  1947.  
  1948. void read_non_jpeg(decompress_info_ptr cinfo)
  1949. {
  1950. JSAMPIMAGE row_ptr;        /* storage for 1 row */
  1951. int i, row;
  1952.  
  1953.     (*cinfo->methods->read_file_header) (cinfo);
  1954.  
  1955.     (*cinfo->methods->d_ui_method_selection) (cinfo);
  1956.     (*cinfo->methods->output_init) (cinfo);
  1957.  
  1958.     if (cinfo->color_map_present)        /* put out color map */
  1959.         (*cinfo->methods->put_color_map) (cinfo, cinfo->actual_number_of_colors, cinfo->colormap);
  1960.  
  1961.     /* alloc pointers & data */
  1962.  
  1963.     row_ptr = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  1964.         (SIZEOF(JSAMPARRAY) * 3);        /* always 3 unless it is color map; but do three */
  1965.     for (i = 0; i < cinfo->num_components; i++)
  1966.         row_ptr[i] = (*cinfo->emethods->alloc_small_sarray)
  1967.             (cinfo->image_width + 1, 1 );
  1968.  
  1969.     /* if only 1 component ie greyscale, color map point all components to first
  1970.          -> this makes a greyscale picture out of one component if non colormap */
  1971.     if (cinfo->num_components < 3){
  1972.         row_ptr[2] = row_ptr[0];
  1973.         row_ptr[1] = row_ptr[0];
  1974.         }
  1975.  
  1976.   /* alloc all of the large storage - ie panning buffer if needed */
  1977.   (*cinfo->emethods->alloc_big_arrays)
  1978.     ((long) 0,                /* no more small sarrays */
  1979.      (long) 0,                /* no more small barrays */
  1980.      (long) 0);                /* no more "medium" objects */
  1981.  
  1982.     for (row = cinfo->image_height; row > 0; row--){
  1983.         check_keybd(cinfo, "E");
  1984.         (*cinfo->methods->get_input_row) (cinfo, row_ptr);
  1985.         (*cinfo->methods->put_pixel_rows) (cinfo, 1, row_ptr);
  1986.         }
  1987.  
  1988.     (*cinfo->methods->output_term) (cinfo);
  1989.  
  1990.     (*cinfo->emethods->free_all) ();
  1991. }
  1992.  
  1993.  
  1994.  
  1995.  
  1996. /*
  1997.  * do everything to show the file
  1998.  *
  1999.  */
  2000.  
  2001. void show_it(decompress_info_ptr cinfo, char * file_name)
  2002. {
  2003. static char path_file_name[file_name_len];    /* path + name to file to view */
  2004. int test_it;
  2005. char pic_file_path[file_name_len];
  2006. FILE *file_in;
  2007.  
  2008. static struct Decompress_methods_struct dc_methods;
  2009. static struct External_methods_struct e_methods;
  2010.  
  2011. /*
  2012.  * do all of the initialization of the JPEG data structure
  2013.  * and set to default values
  2014.  */
  2015.  
  2016. /* Initialize the system-dependent method pointers. */
  2017. cinfo->methods = &dc_methods;
  2018. cinfo->emethods = &e_methods;
  2019.  
  2020. /* Here we supply our own error handler; compare to use of standard error
  2021.  * handler in the previous write_JPEG_file example.
  2022.  */
  2023.  
  2024. emethods = &e_methods;    /* save struct addr for possible access */
  2025. e_methods.error_exit = error_exit; /* supply error-exit routine */
  2026. e_methods.trace_message = trace_message; /* supply trace-message routine */
  2027. e_methods.trace_level = 0;    /* default = no tracing */
  2028. e_methods.num_warnings = 0;    /* no warnings emitted yet */
  2029. e_methods.first_warning_level = 0; /* display first corrupt-data warning */
  2030. e_methods.more_warning_level = 3; /* but suppress additional ones */
  2031.  
  2032. jselmemmgr(&e_methods);    /* memory allocation routines */
  2033. dc_methods.d_ui_method_selection = d_ui_method_selection;
  2034.  
  2035. /* Now OK to enable signal catcher. */
  2036. #ifdef NEED_SIGNAL_CATCHER
  2037.     emethods = &e_methods;
  2038.     signal(SIGINT, signal_catcher);
  2039.     #ifdef SIGTERM            /* not all systems have SIGTERM */
  2040.         signal(SIGTERM, signal_catcher);
  2041.     #endif
  2042. #endif
  2043.  
  2044. /* Set up default JPEG parameters. */
  2045. j_d_defaults(cinfo, TRUE);
  2046.  
  2047. cinfo->colormap = FALSE;        /* default is non colormap picture */
  2048. cinfo->color_map_present = 0;    /* this is not a part of the original JPEG so clear it to be sure */
  2049. zoom_inc = 4;            /* default to no software zoom in */
  2050. row_ordering = NORMAL;    /* for handling bottom up targa's and interlaced gifs when panning */
  2051.  
  2052. /* setup text on the screen ie file name or the defined string from the list of arguements */
  2053. if (picture_text_arguement[0] != 0) strcpy(picture_text, picture_text_arguement);
  2054. else strcpy(picture_text, file_name);
  2055.  
  2056. /*
  2057.  * now setup the offsets for tints, contrasts, brightness
  2058.  */
  2059. red_tint = green_tint = blue_tint = color_scale = contrast_scale = 0;
  2060.  
  2061. strcpy(file_being_viewed, file_name);
  2062.  
  2063. try_4_DOS(picture_description);
  2064.  
  2065. /* setup title on the screen ie file name or the defined string from the list of arguements */
  2066. if (picture_title_arguement[0] != 0) strcpy(picture_title, picture_title_arguement);
  2067. else strcpy(picture_title, picture_description);
  2068.  
  2069. /* load default viewing file if it exists
  2070.  * try local directory first then original directory
  2071.  */
  2072. tint_loaded = 0;        /* flag the graphics routines to speed up if there are no tint offsets loaded from the file */
  2073. if (defaults & use_default_file){
  2074.     strcpy(pic_file_path, file_path);
  2075.     strcat(pic_file_path, viewing_defaults_file);
  2076.     file_in = fopen(pic_file_path, "rb");
  2077.     if (file_in == NULL){
  2078.         strcpy(pic_file_path, original_path);
  2079.         strcat(pic_file_path, viewing_defaults_file);
  2080.         file_in = fopen(pic_file_path, "rb");
  2081.         }
  2082.     if (file_in != NULL){
  2083.         tint_loaded = find_picture_setup(file_in);
  2084.         fclose(file_in);
  2085.         }
  2086.     }
  2087.  
  2088. strcpy(path_file_name, file_path);
  2089. strcat(path_file_name, file_name);
  2090.  
  2091. if ((cinfo->input_file = _fsopen(path_file_name, READ_BINARY, SH_COMPAT)) != NULL) {
  2092.     if (type_of_picture != JPG)
  2093.         buffer_ok = setvbuf(cinfo->input_file, NULL, _IOFBF, buffer_size << 10);    /* buffer for input stream */
  2094.     else
  2095.         buffer_ok = 1;    /* JPEG buffer is always good or we get a memory alloc error */
  2096.  
  2097.     check_file_in(cinfo);
  2098.     key_hit = 0;            /* clear key check flag */
  2099.     gr_row = 0;                /* one shot stuff for pixel drawing routine */
  2100.     read_row = 0;
  2101.     col_cntr=1, row_cntr=1;
  2102.     test_it = setjmp(setjmp_buffer);
  2103.     if (test_it == 0)            /* hop to here if there was a tragic error */
  2104.         if (type_of_picture != JPG)
  2105.             read_non_jpeg(cinfo);
  2106.         else
  2107.             jpeg_decompress(cinfo);
  2108.  
  2109.     fclose(cinfo->input_file);
  2110.     }
  2111. }
  2112.  
  2113.  
  2114.  
  2115.  
  2116. /*
  2117.  * load_config for viewer only
  2118.  *    ie it throws away info about the table of usefull modes
  2119.  *
  2120.  * try may directories for the file
  2121.  * - first a forced path-name can be used
  2122.  * - then try the current path followed the directory that holds the executable
  2123.  * if the forced file name was used then return a 2 instead of a one
  2124.  */
  2125.  
  2126. int load_config_viewer(char *forced_name)
  2127. {
  2128. int    i, j,
  2129.         return_flag = 1,    /* 1 = dvpeg.cfg found, 2 = forced file found and ok */
  2130.         num_custom;        /* index for custom modes */
  2131.  
  2132. FILE *config_file;
  2133.  
  2134. /* clear the list of modes to -1, ie -1 indicates no data, if it is 0 .. XX it is a valid mode */
  2135. for (i=0; i < number_modes_in_list; i++)
  2136.     ok_mode[i] = -1;
  2137.  
  2138. clear_video_struct();
  2139.  
  2140. /* defaults in-case no file exists THESE DEFAULTS ARE BOGUS ==> NO FILE == NO VIEWER */
  2141. shrink = 1;                        /* set default for shrink */
  2142. view_defaults = dithering_bit | smoothing_bit | quantize_bit | panning_bit | ask_size_bit | beep_on;
  2143. any_hi_color  = 0;
  2144. mode_lock = -1;        /* set to no video mode being locked in */
  2145.  
  2146. config_file = NULL;
  2147. if (forced_name != NULL){        /* has a name been forced? */
  2148.     strcpy(config_name, forced_name);
  2149.     config_file = fopen(config_name, "rb");
  2150.     if (config_file != NULL)
  2151.         if (getc(config_file) != cfg_file_marker){        /* if there is a bad marker don't use info */
  2152.             fclose(config_file);
  2153.             config_file = NULL;
  2154.             }
  2155.         else{
  2156.             rewind(config_file);
  2157.             return_flag = 2;        /* return that the config file was used */
  2158.             }
  2159.     }
  2160.  
  2161. if (config_file == NULL){
  2162.     strcpy(config_name, original_path);        /* try boot path for config file */
  2163.     strcat(config_name, config_file_name);
  2164.     config_file = fopen(config_name, "rb");
  2165.     }
  2166.  
  2167. if (config_file == NULL){
  2168.     strcpy(config_name, code_path);        /* try executable dir for config file */
  2169.     strcat(config_name, config_file_name);
  2170.     config_file = fopen(config_name, "rb");
  2171.     }
  2172.  
  2173. if (config_file != NULL){                        /* load the file mode descriptions */
  2174.     if (getc(config_file) != cfg_file_marker){        /* if there is a bad marker don't use info */
  2175.         fclose(config_file);
  2176.         return 0;
  2177.         }
  2178.     mode_lock = getw(config_file);
  2179.     sort_mode = getw(config_file);
  2180.     view_defaults = getw(config_file);                /* various defaults ie grey ... */
  2181.     text_mode_number = getw(config_file);
  2182.     text_width = getw(config_file);
  2183.     text_height = getw(config_file);
  2184.     slideshow_pause = getw(config_file);
  2185.     max_file_records = getw(config_file);
  2186.     defaults = getw(config_file);
  2187.     lock_shrink_value = getw(config_file);
  2188.     buffer_size = getw(config_file);
  2189.     twiddle_factor = getw(config_file);
  2190.     more_defaults = getw(config_file);
  2191.     getw(config_file);        /* for future expansion */
  2192.     getw(config_file);
  2193.  
  2194.     i = -1;            /* now the list of file masks, list is terminated by an empty mask */
  2195.     do{
  2196.         fgets(file_masks[++i], 15, config_file);
  2197.         for (j=0; j < 14; j++)
  2198.             if (file_masks[i][j] == '\n') file_masks[i][j] = 0;        /* remove that \n since it is only needed for loading string in */
  2199.         } while (strlen(file_masks[i]) > 0 && i < max_file_masks - 1);
  2200.  
  2201.     fgets(default_path, file_name_len - 1, config_file);            /* default path ?? */
  2202.     for (i=0; i < file_name_len - 1; i++)
  2203.         if (default_path[i] == '\n') default_path[i] = 0;        /* remove that \n since it is only needed for loading string in */
  2204.     i = -1;
  2205.     while((getw(config_file)) != -1){        /* striped off vidsetup specific info */
  2206.         if (++i >= number_modes_in_list) i--;
  2207.         ok_mode[i] = i;
  2208.         card_id = video_cards[i].card_number = getw(config_file);        /* card_id is the menu default */
  2209.         video_cards[i].x_size = getw(config_file);
  2210.         video_cards[i].y_size = getw(config_file);
  2211.         if ((video_cards[i].resolution = getw(config_file)) > SVGA)
  2212.                 any_hi_color = 1;
  2213.         video_cards[i].set_ax = getw(config_file);
  2214.         video_cards[i].set_bx = getw(config_file);
  2215.         video_cards[i].x_width = getw(config_file);
  2216.         }
  2217.     fclose(config_file);
  2218.  
  2219.     /* copy default directory to the file path */
  2220.     if (strlen(default_path) > 0){
  2221.         strcpy(file_path, default_path);
  2222.         strcat(file_path, "\\");
  2223.         }
  2224.  
  2225.     /* now setup the permenant list of modes as the user has chosen them --> ok_modes
  2226.      *  - the list in ok_mode[] is edited so that hi_color is used for JPEG and SVGA for GIF
  2227.      */
  2228.     for (i = 0; i < number_modes_in_list; i++)
  2229.         all_modes[i] = ok_mode[i];
  2230. #ifdef small_viewer
  2231.     view_defaults |= clear_during_pan;
  2232. /*    more_defaults &= ~slow_gray;        /* default to no quantizing _ever_ */
  2233.     view_defaults &= ~quantize_bit;
  2234.     view_defaults |= grey_bit;
  2235.     buffer_size = 8;        /* smaller buffer to reduce memory usage */
  2236. #endif
  2237.     return return_flag;
  2238.     }
  2239. else
  2240.     return 0;
  2241. }
  2242.  
  2243.  
  2244.  
  2245.  
  2246. /*
  2247.  * setup the info for one file to be printed on the screen
  2248.  * select the color (if its a directory, in the file_list, currently selected ...
  2249.  * move the cursor to the selected spot
  2250.  * cprintf the result
  2251.  * assume that it is on the text screen
  2252.  *
  2253.  * file_index is the index in the dir_info struct
  2254.  * drawing_index is the index for drawing on the screen
  2255.  */
  2256.  
  2257. void setup_file_info(int file_index, int drawing_index)
  2258. {
  2259. char result[60];
  2260. char temp_string[20];
  2261. int i, x_pos, y_pos;
  2262. struct dir_info FAR * temp_info_ptr;    /* generic pointer for tempary use */
  2263.  
  2264. temp_info_ptr = file_info_head + file_index;
  2265.  
  2266. _fstrcpy(temp_string, temp_info_ptr->name);
  2267.  
  2268. sprintf(result, "%13s", temp_string);
  2269.  
  2270. if (defaults & long_file_format && temp_info_ptr->size > 0){
  2271.     i = ((temp_info_ptr->size >> 9) + 1) >> 1;        /* file size in k bytes - rounded up */
  2272.     if (i < 1) i = 1;
  2273.     itoa(i, temp_string, 10);
  2274.     strcat(result, " (");
  2275.     strcat(result, temp_string);
  2276.     strcat(result, "k)");
  2277.     }
  2278. result[column_width] = 0;        /* limit the length if it just happens to be too big for some reason */
  2279.  
  2280. if (file_index == selected_file)
  2281.     textcolor(YELLOW);
  2282. else{
  2283.     if (temp_info_ptr->size == 0)
  2284.         textcolor(LIGHTBLUE);
  2285.     else
  2286.         textcolor(LIGHTGRAY);
  2287.     if (temp_info_ptr->slide_num != 0)    /* red for a selected file */
  2288.         textcolor(LIGHTRED);
  2289.     }
  2290. x_pos = column_width * (drawing_index / per_column) + 1;
  2291. y_pos = ( drawing_index % per_column) + 3;
  2292. gotoxy(x_pos, y_pos);
  2293. cprintf("%s", result);
  2294. }
  2295.  
  2296.  
  2297.  
  2298.  
  2299. /*
  2300.  * The main program.
  2301.  */
  2302.  
  2303. GLOBAL int
  2304. main (int argc, char *argv[])
  2305. {
  2306. int old_selected_file, exit_prog, draw_all;
  2307. int num_slide_show;        /* slide show vars */
  2308. struct Decompress_info_struct cinfo;
  2309. int c, i;
  2310. unsigned int disk_tmp, disk_test;
  2311. char *chr_ptr, *char_index;
  2312. char temp_char[81];
  2313. FILE *config_file, *response_file;
  2314. struct dir_info FAR * old_file_info;        /* pointer to old file data */
  2315. char *input_arg[3];        /* arguements parsed from the response file or a mirror of argv[] */
  2316.  
  2317. current_graphics_mode = -1;        /* set to indicate that we are not in a graphics screen */
  2318. if ((line_buffer_ptr = farmalloc(line_buffer_bytes)) == NULL){
  2319.     prep_for_exit();
  2320.     printf("Could not allocate enough far memory\n");
  2321.     exit(-1);
  2322.     }
  2323.  
  2324. /* memory usage (during viewing) variables */
  2325. near_memory_view = far_memory_view = 0;
  2326.  
  2327. picture_title_arguement[0] = 0;        /* null the string init */
  2328. picture_text_arguement[0] = 0;        /* null the text string */
  2329.  
  2330. get_video();        /* save the current text video mode */
  2331.  
  2332.  
  2333. /* clear the list of file masks */
  2334. for (i=0; i < max_file_masks; i++)
  2335.     file_masks[i][0] = 0;
  2336.  
  2337. /* find the maximum number of drives in the system */
  2338. _dos_getdrive(&disk_tmp);
  2339.  
  2340. i = 0;
  2341. c = 1;
  2342. do{
  2343.     _dos_setdrive(c, &max_drives);
  2344.     _dos_getdrive(&disk_test);
  2345.     if (disk_test == c)        /* we found a good one */
  2346.         drive_list[i++] = c + 'A' - 1;
  2347.     }while (++c <= max_drives && c < drive_list_length);
  2348.  
  2349. _dos_setdrive(disk_tmp, &max_drives);    /* restore drive */
  2350.  
  2351. strcpy(file_path, "C:\\");
  2352. file_path[0] = disk_tmp + 'A' - 1;
  2353. getcurdir(disk_tmp, file_path + 3);
  2354. if (strlen(file_path) > 3)   /* watch out for root because its X:/ already */
  2355.     strcat(file_path, "\\");
  2356. strcpy(original_path, file_path);
  2357.  
  2358. /* Select the input and output files */
  2359.  
  2360. cinfo.output_file = stdout;    /* always the output file */
  2361.  
  2362. /* does the dvpeg.cfg file exist? change .exe to .cfg and fetch from same dir as executable */
  2363. /* set up name for config file (dvpeg.cfg) and assume its in the same dir as vidsetup.exe */
  2364. strcpy(config_name, argv[0]);
  2365.  
  2366. /* knock off file and add dvpeg.cfg to path */
  2367. for (c=strlen(config_name); c >= 0 && config_name[c] != '\\'; c--);
  2368. config_name[c+1] = 0;        /* add dvpeg.cfg in load_config */
  2369. strcpy(code_path, config_name);    /* save the path to the executable */
  2370.  
  2371. config_found = load_config_viewer(NULL);    /* first attempt at finding/loading */
  2372.  
  2373. /* check and parse the arguements 1 at a time,
  2374.  * we could do them all at once but each line can be a response file so check them each
  2375.  */
  2376. c = 1;        /* current arguement ie test for @file as an arguement */
  2377. while (c < argc){
  2378.     if (*argv[c] == '@'){
  2379.         if ((response_file = fopen(argv[c] + 1, "rt")) != NULL)
  2380.             do{
  2381.                 fgets(temp_char, 81, response_file);
  2382.                 temp_char[strlen(temp_char) - 1] = 0;    /* remove \n at the end of the line */
  2383.                 input_arg[1] = temp_char;    /* first arg is always easy and always ends at the first space */
  2384.  
  2385.                 /* everything after the first (if there) space is assumed to be the 2nd arguement */
  2386.  
  2387.                 i = 2;
  2388.                 if ((input_arg[2] = strchr(temp_char, ' ')) != NULL){
  2389.                     i = 3;
  2390.                     *input_arg[2] = 0;    /* set end of string for first arg */
  2391.                     input_arg[2] += 1;
  2392.                     }
  2393.                 parse_switches(&cinfo, i, input_arg, 1);
  2394.                 } while (!feof(response_file));
  2395.             fclose(response_file);
  2396.         }
  2397.     else
  2398.         c = parse_switches(&cinfo, argc, argv, c);
  2399.     c++;
  2400.     }
  2401.  
  2402. /* now check for the existance of files in the file list structure
  2403.  * if they are there clear the slide show flags
  2404.  */
  2405. if (file_info_head != NULL)
  2406.     for (i = max_file_records-1; i >= 0; i--)
  2407.         (file_info_head + i)->slide_num = 0;
  2408.  
  2409. /* ok put up the list of files and let the user pick one */
  2410. if (config_found == 0){
  2411.     printf("Dvpeg configuration file has not been found\n");
  2412.     printf("If you have a Paradise video card please hit ESC now\n and then run vidsetup\n");
  2413.     printf("To continue press any key but ESC\n");
  2414.     if (getch() == escape){
  2415.         prep_for_exit();
  2416.         exit(-1);
  2417.         }
  2418.     strcpy(temp_char, code_path);    /* the path to the executable */
  2419.     strcat(temp_char, "vidsetup -quiet");        /* run it and hope that the config file is made */
  2420.     system(temp_char);
  2421.     config_found = load_config_viewer(NULL);    /* first attempt at finding/loading */
  2422.     }
  2423. if (config_found == 0){
  2424.     prep_for_exit();
  2425.     printf("\nYou must run vidsetup before you can use dvpeg\n");
  2426.     exit(-1);
  2427.     }
  2428.  
  2429.     do_slide_show = 0;
  2430.     num_slide_show = 0;
  2431.     exit_prog = 0;
  2432.     selected_file = 0;
  2433.     old_selected_file = 0;
  2434.     setup_text_screen();            /* setup the right video mode */
  2435.     draw_all = init_screen();        /* signal whole screen redraw */
  2436.     if ((defaults & dont_get_files) == 0)
  2437.         get_files();
  2438.  
  2439.     do{
  2440.         if ((defaults & no_file_list) == 0)
  2441.         if (draw_all){
  2442.                         /* now print the names */
  2443.             for (c = 0; c < per_page && (first_file + c < number_files) && c < max_file_records && file_info_head != NULL; c++)
  2444.                 setup_file_info(c + first_file, c);
  2445.             draw_all = 0;
  2446.             }
  2447.         else        /* only redraw current line & old selection */
  2448.             {
  2449.             setup_file_info(old_selected_file, old_selected_file - first_file);
  2450.  
  2451.             setup_file_info(selected_file, selected_file - first_file);
  2452.             }
  2453.         old_selected_file = selected_file;
  2454.  
  2455.         if (defaults & no_file_list){
  2456.             i = RTN;
  2457.             if (kbhit())
  2458.                 if (get_key() == escape) i = escape;
  2459.             }
  2460.         else
  2461.             i = get_key();
  2462.         switch (i){
  2463.             case escape:
  2464.                 exit_prog = 1;
  2465.                 break;
  2466.             case 'a':
  2467.             case 'A':    /* select all for slide show */
  2468.                 num_slide_show = 0;
  2469.                 for (i = 0;    i < max_file_records; i++)
  2470.                     if ((file_info_head + i)->size > 0)
  2471.                         (file_info_head + i)->slide_num = ++num_slide_show;
  2472.                 draw_all = init_screen();
  2473.                 break;
  2474.             case 'S':        /* slide show trigger for continous */
  2475.                 defaults |= slide_show_continous;
  2476.             case 's':        /* trigger for one shot slide show */
  2477.                 slide_show(&cinfo);
  2478.                 setup_text_screen();            /* setup the right video mode */
  2479.                 draw_all = init_screen();
  2480.                 break;
  2481.             case delete:        /* delete a file */
  2482.                 if ((file_info_head + selected_file)->size > 0){    /* ie only for files not directories or drives */
  2483.                     strcpy(temp_char, "del ");
  2484.                     strcat(temp_char, file_path);
  2485.                     _fstrcat(temp_char, (file_info_head + selected_file)->name);
  2486.                     system(temp_char);
  2487.                     get_files();
  2488.                     draw_all = init_screen();
  2489.                     }
  2490.                 break;
  2491.             case ' ':        /* slide show list ie add or delete */
  2492.                 if ((file_info_head + selected_file)->size > 0){        /* is it a file or directory/drive ? */
  2493.                     if ((file_info_head + selected_file)->slide_num > 0)
  2494.                         {    /* delete an item */
  2495.                         c = (file_info_head + selected_file)->slide_num;
  2496.  
  2497.                         /* deleting is done by setting the current files' flag to 0 and subtracting 1 from any one that has a value greater than it */
  2498.  
  2499.                         (file_info_head + selected_file)->slide_num = 0;
  2500.                         for (i = max_file_records-1; i >= 0; i--)
  2501.                             if ((file_info_head + i)->slide_num > c)
  2502.                                 (file_info_head + i)->slide_num--;
  2503.                         num_slide_show--;
  2504.                         }
  2505.                     else    /* add it */
  2506.                         (file_info_head + selected_file)->slide_num = ++num_slide_show;
  2507.                     }
  2508.                 selected_file++;
  2509.                 break;
  2510.             case RTN:        /* change directory ?? */
  2511.                 if ((file_info_head + selected_file)->size == 0){
  2512.                     if ((file_info_head + selected_file)->name[0] == '[')
  2513.                         change_drive((file_info_head + selected_file)->name[1]);
  2514.                     else
  2515.                         if ((file_info_head + selected_file)->name[0] == '.'){
  2516.                             /* do nothing on a . but move up in tree on .. */
  2517.                             if ((file_info_head + selected_file)->name[1] == '.'){
  2518.                                 for (c=strlen(file_path)-2; c >= 0 && file_path[c] != '\\'; c--);
  2519.                                 file_path[c+1] = 0;
  2520.                                 }
  2521.                             }
  2522.                         else{                /* its a directory down - add it to list */
  2523.                         _fstrcat(file_path, (file_info_head + selected_file)->name);
  2524.                             strcat(file_path, "\\");
  2525.                             }
  2526.                     get_files();
  2527.                     draw_all = init_screen();
  2528.                     }
  2529.                 else        /* if the menu is turned off, do not exit here until ESC is hit */
  2530.                     {
  2531.                     show_next_file = 0;
  2532.                     time_at_start = 0;
  2533.                     do{
  2534.                         c = view_defaults;    /* save default ie it may have changed */
  2535.                         i = show_next_file;        /* preserve status to determine if we restore view_defaults or not */
  2536.                         if (show_next_file != 0)
  2537.                             view_defaults &= (~ask_size_bit);    /* turn off second menu */
  2538.                         show_next_file = 0;    /* zero it to see if it was changed again */
  2539.  
  2540.                         _fstrcpy(temp_char, (file_info_head + selected_file)->name);
  2541.                         show_it(&cinfo, temp_char);
  2542.  
  2543.                         if (i != 0)        /* if the menu was hidden then restore view_defaults */
  2544.                             view_defaults= c;
  2545.                         if (show_next_file == 1 && selected_file < number_files)
  2546.                             selected_file++;
  2547.                         if (show_next_file == -1 && selected_file > 0)
  2548.                             selected_file--;
  2549.  
  2550.                         /* if the menu is turned off just cycle thru the files again and again until ESC */
  2551.  
  2552.                         if (defaults & no_file_list){
  2553.                             if (show_next_file == 0) exit_prog = 1;
  2554.                             if (show_next_file == 1 && selected_file >= number_files)
  2555.                                 selected_file = 0;
  2556.                             if (show_next_file == -1 && selected_file <= 0)
  2557.                                 selected_file = number_files - 1;
  2558.                             }
  2559.                         }
  2560.                     while (show_next_file != 0);
  2561.  
  2562.                     if ((defaults & no_file_list) == 0){
  2563.                         setup_text_screen();            /* setup the right video mode */
  2564.                         draw_all = init_screen();
  2565.                         }
  2566.                     }
  2567.                 break;
  2568.             case arrow_up:
  2569.                 selected_file--;
  2570.                 break;
  2571.             case arrow_down:
  2572.                 selected_file++;
  2573.                 break;
  2574.             case arrow_left:
  2575.                 if (selected_file - per_column >= first_file)
  2576.                     selected_file -= per_column;
  2577.                 break;
  2578.             case arrow_right:            /* stop going off right edge */
  2579.                 if (selected_file + per_column < first_file + per_page)
  2580.                     selected_file += per_column;
  2581.                 break;
  2582.             case page_up:
  2583.                 selected_file -= per_page;
  2584.                 break;
  2585.             case page_down:
  2586.                 selected_file += per_page;
  2587.                 break;
  2588.             case home:
  2589.                 selected_file = 0;
  2590.                 break;
  2591.             case end:
  2592.                 selected_file = number_files;
  2593.                 break;
  2594.  
  2595. #ifndef small_viewer        /* reduced viewer without ability to change options */
  2596.             case F1:
  2597.                     open_window(40, 14);
  2598.                     cprintf("up/down arrow - select a file\r\n");
  2599.                     cprintf("enter - check out that picture\r\n");
  2600.                     cprintf("space - select for slideshow\r\n");
  2601.                     cprintf("S, s - slide show (S = continous)\r\n");
  2602.                     cprintf("F2 - change drive\r\n");
  2603.                     cprintf("F3, F7 - change defaults\r\n");
  2604.                     cprintf("F4 - change mask for files\r\n");
  2605.                     cprintf("F5 - change sorting criteria\r\n");
  2606.                     cprintf("F6 - change file path\r\n");
  2607.                     cprintf("\nMemory: %lu + %lu bytes",(unsigned long) coreleft(), (unsigned long)farcoreleft());
  2608.                     cprintf("\r\nDuring pic: %lu + %lu bytes",(unsigned long) near_memory_view, (unsigned long)far_memory_view);
  2609.                     getch();
  2610.                     draw_all = init_screen();
  2611.                     break;
  2612.             case F2:        /* change directory and default to the current path on that drive */
  2613.                 open_window(40,10);
  2614.                 cprintf("Current drive is %c\r\n",file_path[0]);
  2615.                 cprintf("What is the new drive?\r\n");
  2616.                 change_drive(toupper(getch()));
  2617.                 draw_all = init_screen();
  2618.                 break;
  2619.             case F3:        /* see if user wants to turn off next window */
  2620.                 do{
  2621.                     open_window(46,18);
  2622.                     show_defaults(1, 1);
  2623.                     } while ( change_defaults(getch(), 1));
  2624.  
  2625.                 draw_all = init_screen();
  2626.                 break;
  2627.             case F4:                /* get the file mask */
  2628.                 open_window(40,10);
  2629.                 if (get_file_masks())    /* if anything was changed */
  2630.                     get_files();
  2631.                 draw_all = init_screen();
  2632.                 break;
  2633.             case F5:                /* change the sort order */
  2634.                 open_window(40,10);
  2635.                 cprintf("Sort order is: ");
  2636.                 switch (sort_mode){
  2637.                     case NONE:
  2638.                                     cprintf("unsorted");
  2639.                                     break;
  2640.                     case FF_NAME:
  2641.                                     cprintf("by name");
  2642.                                     break;
  2643.                     case FF_SIZE:
  2644.                                     cprintf("by size");
  2645.                                     break;
  2646.                     case FF_DATE:
  2647.                                     cprintf("by date");
  2648.                                     break;
  2649.                     }
  2650.                 cprintf("\r\nchoose: Unsorted, Name, Size, Date\r\n");
  2651.                 c = getch();
  2652.                 switch (c){
  2653.                     case 'N':
  2654.                     case 'n':   sort_mode = FF_NAME;
  2655.                                     break;
  2656.                     case 'U':
  2657.                     case 'u':
  2658.                                     sort_mode = NONE;
  2659.                                     break;
  2660.                     case 'S':
  2661.                     case 's':
  2662.                                     sort_mode = FF_SIZE;
  2663.                                     break;
  2664.                     case 'D':
  2665.                     case 'd':
  2666.                                     sort_mode = FF_DATE;
  2667.                                     break;
  2668.                     }
  2669.                 get_files();
  2670.                 draw_all = init_screen();
  2671.                 break;
  2672.             case F6:
  2673.                 open_window(50, 10);
  2674.                 cprintf("The file path is: %25s\r\n\n", file_path);
  2675.                 cprintf("What is the new path (ie d:\\gifs)?\r\n");
  2676.                 if (get_line(config_name, 25) > 0){
  2677.                     strcpy(file_path, config_name);
  2678.                     strcat(file_path, "\\");
  2679.                     get_files();
  2680.                     }
  2681.                 draw_all = init_screen();
  2682.                 break;
  2683.             case F7:
  2684.                 i = c = 0;        /* use i, c to check for any change that indicates a new file list is needed */
  2685.                 open_window(40, 20);
  2686.                 do{
  2687.                     i |= c;
  2688.                     show_extra_defaults();
  2689.                     }while (    (c = change_extra_defaults(getch())) != 0 );
  2690.                 if ((i & 0x4) != 0) setup_text_screen();            /* setup the right video mode */
  2691.                 if ((i & 0x2) != 0) get_files();
  2692.                 draw_all = init_screen();
  2693.                 break;
  2694. #endif
  2695.             }
  2696.         if ((defaults & no_file_list) == 0){
  2697.             if (selected_file < 0) selected_file = 0;
  2698.             if (selected_file >= number_files) selected_file = number_files - 1;
  2699.  
  2700.             if (selected_file >= first_file + per_page){    /* went off bottom of page - center on chosen file */
  2701.                 first_file = selected_file - (per_page >> 1);
  2702.                 if (first_file >= number_files - per_page)
  2703.                     first_file = number_files - per_page;
  2704.                 draw_all = init_screen();
  2705.                 }
  2706.             if (selected_file < first_file){        /* went off top of screen - try to center on chosen file */
  2707.                 first_file = selected_file - (per_page >> 1);
  2708.                 if (first_file < 0)
  2709.                     first_file = 0;
  2710.                 draw_all = init_screen();
  2711.                 }
  2712.             }
  2713.     }while (!exit_prog);
  2714.  
  2715. prep_for_exit();
  2716.  
  2717. return 1;            /* indicate success */
  2718. }
  2719.