10!  OUTPUT 2 USING "#,K";"<lf>REN<cr>INDENT<cr><lf>RE-STORE ""PLOT_H""<cr>"
20    !
30 !  EDIT Test_prog
40 !  EDIT Plot_plot
50 !  EDIT Plot_good_csize
60 !  EDIT Plot_set_viewp
70 !  EDIT Plot_do_axes
80 !  EDIT Plot_do_data
90 !  EDIT Plot_grid
100!  EDIT Plot_x_pixel
110!  EDIT Plot_y_pixel
120!  EDIT Plot_background
130!  EDIT Plot_do_mkr
140!  EDIT Plot_move_mkr
150!  EDIT Plot_have_color
160!  EDIT Plot_set_color
170!  EDIT Plot_eng_format
180!  EDIT Plot_bold_label
190!  EDIT Plot_make_x
200!  EDIT Plot_make_y
210!
220   !
230 Plot_doc: ! 19-Jun-86
240 ! ******************************************************************
250 !               PLOT (Plot_) MODULE DESCRIPTION
260 ! Subprograms in the PLOT file are called by DISP subprograms
270 ! to do graphics.  PLOT subprograms interface between the DISP subprograms
280 ! and the graphics commands, and hide some of the hardware dependencies.
290 !
300 !------------------------------------------------------------------
310 !
320 ! ******************************************************************
330 Test_prog:  !---------------------------------------------------------
340  ! LOADSUB ALL FROM "USER"
350  !
360   !  <PLACE TEST CODE HERE>
370   CALL Plot_plot
380   CSIZE FNPlot_good_csize
390   DISP "filling data_buffer"
400   Rl=1024
410   Num_bins=Rl
420   ALLOCATE Data_buffer(1:20,0:Rl-1),Data_header(1:20,1:10)
430   DIM Plot_array(0:4095,1:2)
440   FOR B=1 TO 4
450     Data_header(B,1)=0    !offset
460     Data_header(B,2)=1    !scale factor
470     Data_header(B,3)=1    !overload
480     Data_header(B,4)=2     !log
490     Data_header(B,5)=100   !log of zero
500     Data_header(B,6)=100  !average
510   NEXT B
520   FOR I=0 TO Rl-5
530     Data_buffer(1,I)=.0011+I/Rl
540     FOR B=2 TO 4
550       Data_buffer(B,I)=Data_buffer(1,I)
560     NEXT B
570   NEXT I
580   DISP "PLOTTING"
590   !
600   Plot_title$="title"
610   X_units$="Sec"
620   Y_units$="dBpC"
630   X_min=128
640   X_max=51200
650   Y_min=.001
660   Y_max=1
670   Start_bin=0
680   Do_log_x=0
690   Do_log_y=1
700   FOR Num_plots=1 TO 14 STEP 2
710     GCLEAR
720     CLIP ON
730     FOR Plot_num=1 TO 1
740       DISP "num_plots, plot_num ";Num_plots,Plot_num
750       !
760       CALL Plot_set_viewp(Num_plots,(Plot_num),X_label_length,5,0)
770       CALL Plot_do_axes(Plot_title$,X_units$,Y_units$,X_min,X_max,Y_min,Y_max,X_label_length)
780       CALL Plot_set_viewp(Num_plots,(Plot_num),X_label_length,5,1)
790       Average=Data_header(Plot_num,6)
800       Overload=Data_header(Plot_num,3)
810       REDIM Plot_array(Start_bin:Start_bin+Num_bins-1,1:2)
820       CALL Plot_make_y(Data_buffer(*),Data_header(*),Plot_array(*),Plot_num,Start_bin,Start_bin+Num_bins-1,Do_log_y,Offset,Scale_factor)
830       CALL Plot_make_x(Plot_array(*),Do_log_x,X_min,X_max)
840       CALL Plot_background
850       CALL Plot_grid(X_min,X_max,Y_min,Y_max,Do_log_x,Do_log_y)
860       CALL Plot_do_data(Plot_array(*),Overload,"HI",Y_min,Y_max,Offset,Scale_factor,Do_log_y)
870       IF 1 THEN 
880         REPEAT
890           CALL Plot_do_mkr(Plot_array(*),X_units$,Y_units$,X_min,X_max,Y_min,Y_max,Offset,Scale_factor,Do_log_y)
900           CALL Plot_move_mkr(Plot_array(*),X_units$,X_min,X_max)
910         UNTIL 0
920       END IF
930     NEXT Plot_num
940     PAUSE
950     WAIT .5
960   NEXT Num_plots
970   END
980   ! PAGE -> 
990   !************************************************************************
1000 Plot_plot:SUB Plot_plot
1010  !This subprogram declares and initializes common blocks used by subprograms in the PLOT file.
1020  !Plot_ common variables are used only by other Plot_ subprograms.
1030  !The graphics display is initialized and all pen colors are defined.
1040  !------------------------------------------------------------------------
1050    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
1060    COM /Plot_viewp/ Left,Right,Top,Bottom      !last viewport command
1070    COM /Plot_mkr/ INTEGER Mkr_bin
1080    Mkr_bin=-1
1090    INTEGER A(0:5)
1100    GINIT
1110    ON ERROR GOTO No_color
1120    PLOTTER IS CRT,"INTERNAL";COLOR MAP
1130    Have_color=1
1140    Use_color=1
1150    OFF ERROR 
1160    !set up color map so compliment shows up
1170    GESCAPE CRT,1;A(*)
1180    Num_colors=A(0)
1190    !
1200    !All colors are defined here.  In order for the marker
1210    !cursor to be visible, the compliment of the pen number must
1220    !be a pen number whose color is visible.  White seems to work
1230    !for most.
1240    SET PEN 1 INTENSITY 1,1,1               !labels etc
1250    SET PEN Num_colors-1-1 INTENSITY 0,0,0  !compliment of 1 for marker locator
1260    SET PEN 2 INTENSITY 1,0,0               !red
1270    SET PEN 5 INTENSITY 0,1,1               !cyan for traces
1280    SET PEN Num_colors-5-1 INTENSITY 1,1,1  !compliment of 5
1290    SET PEN 6 INTENSITY 1,.4,.2             !brick red grid
1300    SET PEN Num_colors-6-1 INTENSITY 1,1,1  !compliment of 6
1310    SET PEN 7 INTENSITY .3,.3,.3            ! for background
1320    SET PEN Num_colors-7-1 INTENSITY 1,1,1  !compliment of 7
1330    !
1340    IF POS(SYSTEM$("CRT ID"),"CGB") THEN   !bit mapped
1350      CONTROL CRT,15;1       !white disp
1360      CONTROL CRT,16;5       !cyan softkeys
1370    ELSE
1380      CONTROL CRT,15;136     !white disp
1390      CONTROL CRT,16;140     !cyan softkeys
1400    END IF
1410    GOTO Get_config
1420 No_color:OFF ERROR 
1430    PLOTTER IS CRT,"INTERNAL"
1440    Have_color=0
1450    Use_color=0
1460 Get_config:!
1470    GESCAPE CRT,3;A(*)       !gets CRT pixel size in A(*)
1480    X_pixels=A(2)
1490    Y_pixels=A(3)
1500  SUBEND
1510  !************************************************************************
1520 Plot_good_csize:DEF FNPlot_good_csize
1530  !This function returns minimum CSIZE for no character distortion.
1540    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
1550    RETURN 100*15/Y_pixels   !15 pix/char.cell,  Y pix, 100 gdus
1560  FNEND
1570  ! PAGE -> 
1580  !************************************************************************
1590 Plot_set_viewp:SUB Plot_set_viewp(Num_plots,Plot_num,X_label_length,Y_label_length,Pixels_in)
1600  !This subprogram is called prior to plotting to setup viewport for next
1610  !plot.
1620  !INPUTS:  Num_plots:  1..16   Total number of plots to be done.
1630  !         Plot_num:   1..Num_plots  Current plot number
1640  !         Y_label_length 1..12  Number of characters to leave room for
1650  !                     at the left of the viewport
1660  !         Pixels_in:  The number of pixels to shrink the viewport by.
1670  !                     Used to avoid drawing on the frame.
1680  !OUTPUTS: X_label_length  Number of characters that there is room for
1690  !                     in the title and along the x axis
1700  !------------------------------------------------------------------------
1710    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
1720    COM /Plot_viewp/ Left,Right,Top,Bottom
1730    Num_plots=MAX(1,MIN(16,Num_plots))
1740    Plot_num=MAX(1,MIN(Num_plots,Plot_num))
1750    Y_label_length=MAX(0,MIN(12,Y_label_length))
1760    STATUS CRT,13;Crt_height
1770    Y_offset=100*(6.5/Crt_height)  !start plots above DISP line (line 6)
1780    Y_offset=MIN(Y_offset,24)      !
1790    Y_plots=PROUND(SQR(Num_plots)+.49999,0)
1800    X_plots=INT(Num_plots/Y_plots+.9999)
1810    X=(Plot_num-1) MOD X_plots
1820    Y=(Plot_num-1) DIV X_plots
1830    Y=Y_plots-Y-1      !to plot top first
1840    X_size=100*RATIO/X_plots
1850    Y_size=(100-Y_offset)/Y_plots
1860    Left=X*X_size+Y_label_length*.6*FNPlot_good_csize
1870    IF Plot_num<>Num_plots THEN  !not last plot
1880      Right=(X+1)*X_size
1890    ELSE  !force last plot to use remainder of screen
1900      Right=X_plots*X_size
1910    END IF
1920    Bottom=Y_offset+Y*Y_size+FNPlot_good_csize     !+ 1 char
1930    Top=Y_offset+(Y+1)*Y_size-FNPlot_good_csize
1940    IF Pixels_in<>0 THEN 
1950      Left=Left+Pixels_in*100*RATIO/X_pixels
1960      Right=Right-Pixels_in*100*RATIO/X_pixels
1970      Bottom=Bottom+Pixels_in*100/Y_pixels
1980      Top=Top-Pixels_in*100/Y_pixels
1990    END IF
2000    VIEWPORT Left,Right,Bottom,Top
2010    X_label_length=INT((Right-Left)/(.6*FNPlot_good_csize)+.1)
2020  SUBEND
2030  ! PAGE -> 
2040  !************************************************************************
2050 Plot_do_axes:SUB Plot_do_axes(Plot_title$,X_units$,Y_units$,X_min,X_max,Y_min,Y_max,X_label_length)
2060  !This subprogram labels the axis of one plot.
2070  !INPUTS:  Plot_title$, X_units$, Y_units$:  strings
2080  !         X_min,X_max,Y_min,Y_max:  plot boundaries in real-world units.
2090  !         X_label_length: The number of characters that will fit along
2100  !                     the X axis.
2110  !------------------------------------------------------------------------
2120    DIM Min$[18],Max$[18],Prefix$[1]
2130    Left=1
2140    Right=2
2150    Bottom=3
2160    Top=4
2170    GRAPHICS ON
2180    PEN 1
2190    LINE TYPE 1
2200    WINDOW Left,Right,Bottom,Top
2210    FRAME
2220    CLIP OFF
2230    LDIR 0
2240    GOSUB Plot_title
2250    IF X_units$<>"" THEN GOSUB Plot_x
2260    IF Y_units$<>"" THEN GOSUB Plot_y
2270    SUBEXIT
2280 Plot_title:  !------------------------------------------------------
2290    LORG 1
2300    MOVE Left,Top
2310    IF LEN(Plot_title$)>X_label_length THEN 
2320      LABEL Plot_title$[1,X_label_length]
2330    ELSE
2340      LABEL Plot_title$
2350    END IF
2360    RETURN 
2370 Plot_x:     !--------------------------------------------------------
2380    IF (X_min=0) OR (X_max=0) THEN 
2390      Digits=3
2400    ELSE
2410      Digits=LGT(ABS(X_min/(X_max-X_min)))+1   !min num of sig digits
2420      Digits=MAX(3,MIN(7,Digits))
2430    END IF
2440    CALL Plot_eng_format(X_min,X_max,Min$,Max$,Digits,Prefix$)
2450    Length=X_label_length
2460    IF Min$<>"0" THEN Min$=Min$&Prefix$
2470    IF Max$<>"0" THEN Max$=Max$&Prefix$
2480    !start labeling, keeping track of how much room is left
2490    IF Length>=LEN(Min$) THEN   !if there is room for left label
2500      LORG 3
2510      MOVE Left,Bottom
2520      LABEL Min$
2530      Length=Length-LEN(Min$)
2540    END IF
2550    IF Length>LEN(Max$) THEN 
2560      LORG 9
2570      MOVE Right,Bottom
2580      LABEL Max$
2590      Length=Length-LEN(Max$)
2600    END IF
2610    IF (X_label_length-2*MAX(LEN(Min$),LEN(Max$)))>LEN(X_units$) THEN           !if room in center
2620      LORG 6
2630      MOVE (Left+Right)/2,Bottom
2640      LABEL X_units$
2650    END IF
2660    RETURN 
2670 Plot_y:     !--------------------------------------------------------
2680    CALL Plot_eng_format(Y_min,Y_max,Min$,Max$,3,Prefix$)
2690    IF Min$<>"0" THEN Min$=Min$&Prefix$
2700    IF Max$<>"0" THEN Max$=Max$&Prefix$
2710    LORG 7
2720    MOVE Left,Bottom
2730    IF Min$<>Max$ THEN LABEL Min$
2740    LORG 9
2750    MOVE Left,Top
2760    LABEL Max$
2770    LORG 8
2780    MOVE Left,(Top+Bottom)/2
2790    LABEL Y_units$
2800    RETURN 
2810  SUBEND
2820  ! PAGE -> 
2830  !************************************************************************
2840 Plot_do_data:SUB Plot_do_data(Plot_array(*),Overload,Message$,Y_min,Y_max,Offset,Scale_factor,Do_log_y,OPTIONAL Ltype)
2850  !This subprogram draws the data for one plot.  To save time, the data can
2860  !be "scaled" by Offset and Scale_factor using the WINDOW command.
2870  !
2880  !INPUTS:  Plot_array(*):       Array of XY pairs ready for a PLOT command.
2890  !                              Plot_array(*,1) = X = bin numbers.  Plot_array(*,2)
2900  !                              = Y = un-scaled Y data.
2910  !         Overload, Message$:  Used to annotate the plot.
2920  !         Y_min,Y_max:         Plot boundary values in real world units.
2930  !         Offset,
2940  !         Scale_factor:        Scaling for Y values.
2950  !         Do_log_y:            Flag, non-zero if y axis is logarithmic.
2960  !       OPTIONAL
2970  !         Ltype:               Line type information
2980  !-----------------------------------------------------------------------
2990    INTEGER Start_bin,Stop_bin
3000    GRAPHICS ON
3010    LINE TYPE 1
3020    CLIP ON
3030    Start_bin=BASE(Plot_array,1)
3040    Stop_bin=BASE(Plot_array,1)+SIZE(Plot_array,1)-1
3050    IF Scale_factor=0 THEN 
3060      CALL User_error("ERROR: Data_header scale factor is zero. (Plot_do_data)")
3070      Scale_factor=1
3080    END IF
3090    WINDOW 0,1,0,1
3100    LORG 9
3110    MOVE 1,1
3120    PEN 1
3130    IF Message$<>"" THEN LABEL Message$&" "
3140    IF Overload THEN 
3150      LORG 3
3160      MOVE 0,1
3170      IF FNPlot_use_color THEN PEN 3
3180      LABEL "OVLD "
3190      LORG 9
3200    END IF
3210    IF FNPlot_use_color THEN PEN 5
3220    MOVE 0,0   !to avoid error 19 if next window is 1E-7 (BASIC bug?)
3230    !note that the window is used to scale the data
3240    IF FNDisp_in_ds_h THEN 
3250      Sc_start_bin=FNDisp_vs_start
3260      Sc_stop_bin=FNDisp_vs_stop
3270    ELSE
3280      Sc_start_bin=Start_bin
3290      Sc_stop_bin=Stop_bin
3300    END IF
3310    IF NPAR=9 THEN LINE TYPE Ltype
3320    IF Do_log_y THEN 
3330      WINDOW Sc_start_bin,Sc_stop_bin,LGT(Y_min)*Scale_factor+Offset,LGT(Y_max)*Scale_factor+Offset
3340    ELSE
3350      WINDOW Sc_start_bin,Sc_stop_bin,Y_min*Scale_factor+Offset,Y_max*Scale_factor+Offset
3360    END IF
3370    ON ERROR GOTO Plot_error
3380    MOVE Plot_array(Start_bin,1),Plot_array(Start_bin,2)
3390    PLOT Plot_array(*)
3400    MOVE 0,0
3410    LINE TYPE 1
3420 Plot_error:OFF ERROR 
3430  SUBEND
3440  ! PAGE -> 
3450  !************************************************************************
3460 Plot_grid:SUB Plot_grid(X_min,X_max,Y_min,Y_max,Do_log_x,Do_log_y)
3470  !This subprogram draws linear or log grids.  If linear, puts up between 4
3480  !and 10 grid lines spaced at 1, 2, or 5 units.  If log, puts up solid
3490  !lines at 1  and 1 dotted line at 5 or 4 dotted lines at 2, 4, 6, 8.
3500    IF FNPlot_use_color THEN PEN 6
3510    CLIP ON
3520    X_pwr=PROUND(LGT(X_max-X_min)-.51,0)
3530    Y_pwr=PROUND(LGT(Y_max-Y_min)-.51,0)
3540    X_tic=10^X_pwr     !gives 1 to 10 tics every 1 or 10 or 100 ...
3550    Y_tic=10^Y_pwr
3560    SELECT (X_max-X_min)/X_tic  !number of tics
3570    CASE 2 TO 3.9
3580      X_tic=X_tic/2  !tic spacing of 5
3590    CASE <2
3600      X_tic=X_tic/5  !tic spacing of 2
3610    END SELECT
3620    SELECT (Y_max-Y_min)/Y_tic  !number of tics
3630    CASE 2 TO 3.9
3640      Y_tic=Y_tic/2  !tic spacing of 5
3650    CASE <2
3660      Y_tic=Y_tic/5  !tic spacing of 2
3670    END SELECT
3680    IF NOT (Do_log_x OR Do_log_y) THEN !linear, linear
3690      WINDOW X_min,X_max,Y_min,Y_max
3700      LINE TYPE 4
3710      GRID X_tic,Y_tic,PROUND(X_min,X_pwr),PROUND(Y_min,Y_pwr)
3720    ELSE   !at least one is log
3730      IF Do_log_x THEN 
3740        WINDOW LGT(X_min),LGT(X_max),0,1
3750        LINE TYPE 1
3760        GRID 1,3,LGT(1),-1         !X grid at 1, no Y
3770        LINE TYPE 4
3780        IF 1/(FNPlot_x_pixel*LGT(X_max/X_min))>40 THEN  !if enought pixels/decade
3790          GRID 1,3,LGT(2),-1
3800          GRID 1,3,LGT(4),-1
3810          GRID 1,3,LGT(6),-1
3820          GRID 1,3,LGT(8),-1
3830        ELSE  !not enough pixels/decade
3840          GRID 1,3,LGT(5),-1
3850        END IF
3860      ELSE
3870        WINDOW X_min,X_max,0,1
3880        LINE TYPE 4
3890        GRID X_tic,3,PROUND(X_min,X_pwr),-1
3900      END IF
3910      IF Do_log_y THEN 
3920        WINDOW 0,1,LGT(Y_min),LGT(Y_max)
3930        LINE TYPE 1
3940        GRID 3,1,-1,LGT(1)         !y grid at 1, no x
3950        LINE TYPE 4
3960        IF 1/(FNPlot_y_pixel*LGT(Y_max/Y_min))>40 THEN  !if enought pixels/decade
3970          GRID 3,1,-1,LGT(2)
3980          GRID 3,1,-1,LGT(4)
3990          GRID 3,1,-1,LGT(6)
4000          GRID 3,1,-1,LGT(8)
4010        ELSE  !not enough pixels/decade
4020          GRID 3,1,-1,LGT(5)
4030        END IF
4040      ELSE
4050        WINDOW 0,1,Y_min,Y_max
4060        LINE TYPE 4
4070        GRID 3,Y_tic,-1,PROUND(Y_min,Y_pwr)
4080      END IF
4090    END IF
4100    LINE TYPE 1
4110  SUBEND
4120  !*****************************************************************
4130 Plot_x_pixel:DEF FNPlot_x_pixel
4140  !This function returns the horizontal size of one pixel as a ratio of the
4150  !current window size.   1/FNPlot_x_pixel is the number of X pixels in
4160  !the current viewport.
4170    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
4180    COM /Plot_viewp/ Left,Right,Top,Bottom !last viewport command
4190    IF Left+Right=0 THEN CALL User_stop("PROGRAM ERROR: Plot_set_veiwp not called before FNPlot_x_pixel")
4200    RETURN 1/(X_pixels*.01*(Right-Left)/RATIO)
4210  FNEND
4220  !*****************************************************************
4230 Plot_y_pixel:DEF FNPlot_y_pixel
4240  !This function returns the vertical size of one pixel as a ratio of the
4250  !current window size.  1/FNPlot_y_pixel is the number of y pixels in
4260  !the current viewport.
4270    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
4280    COM /Plot_viewp/ Left,Right,Top,Bottom !last viewport command
4290    IF Left+Right=0 THEN CALL User_stop("PROGRAM ERROR: Plot_set_veiwp not called before FNPlot_y_pixel")
4300    RETURN 1/(Y_pixels*.01*(Top-Bottom))
4310  FNEND
4320  !*****************************************************************
4330 Plot_background:SUB Plot_background
4340  !This subprogram erases the current viewport by drawing a rectangle using
4350  !background color.
4360    WINDOW 0,1,0,1
4370    MOVE 0,0
4380    IF FNPlot_use_color THEN 
4390      AREA PEN 7   !background color set in Plot_plot
4400    ELSE
4410      AREA PEN -1  !erase
4420    END IF
4430    RECTANGLE 1,1,FILL
4440    AREA PEN 1
4450  SUBEND
4460  ! PAGE -> 
4470  !*****************************************************************
4480 Plot_do_mkr:SUB Plot_do_mkr(Plot_array(*),X_units$,Y_units$,X_min,X_max,Y_min1,Y_max1,Offset,Scale_factor,Do_log_y)
4490  !This subprogram operates the marker on one trace.  Pass parameters are
4500  !similar to Plot_do_data.
4510    COM /Plot_mkr/ INTEGER Mkr_bin  !for memory between calls
4520    INTEGER Start_bin,Stop_bin,Last_marker
4530    DIM D_line$[80]
4540    GRAPHICS INPUT IS KBD,"KBD"   !use keyborad arrows to move marker
4550    LINE TYPE 1
4560    CLIP ON
4570    Start_bin=BASE(Plot_array,1)
4580    Stop_bin=BASE(Plot_array,1)+SIZE(Plot_array,1)-1
4590    Per_bin_x=(X_max-X_min)/(Stop_bin-Start_bin)
4600    IF Mkr_bin=-1 THEN Mkr_bin=(Stop_bin+Start_bin)/2  !un initialized
4610    Mkr_bin=MAX(Start_bin,MIN(Stop_bin,Mkr_bin))
4620    IF Scale_factor=0 THEN 
4630      CALL User_error("ERROR: Data_header scale factor is zero (Plot_do_mkr)")
4640      Scale_factor=1
4650    END IF
4660    IF Do_log_y THEN 
4670      Y_min=LGT(Y_min1)
4680      Y_max=LGT(Y_max1)
4690    ELSE
4700      Y_min=Y_min1
4710      Y_max=Y_max1
4720    END IF
4730    MOVE 0,0   !to avoid error 19 if next window is 1E-7 (BASIC bug)
4740    WINDOW Start_bin,Stop_bin,Y_min,Y_max
4750    CLIP ON
4760    ! Marker_gain is a fudge factor that allows the marker to hit each bin
4770    ! The min locator change is 1 pixel.  Marker_gain maps one pixel into
4780    ! one bin.
4790    Marker_gain=1/(SIZE(Plot_array,1)*FNPlot_x_pixel)
4800    Y=(Plot_array(Mkr_bin,2)-Offset)/Scale_factor
4810    SET LOCATOR Mkr_bin,MAX(Y_min,MIN(Y_max,Y))
4820    SET ECHO Plot_array(Mkr_bin,1),MAX(Y_min,MIN(Y_max,Y))
4830    GOSUB Disp_mkr
4840    REPEAT
4850      DISABLE 
4860      READ LOCATOR Locator_x,Dummy
4870      Mkr_bin=MAX(Start_bin,MIN(Stop_bin,Mkr_bin+(Locator_x-Mkr_bin)*Marker_gain))
4880      IF FNDisp_in_ds_h AND NOT FNDisp_auto_c THEN 
4890        Y=Dummy
4900      ELSE
4910        Y=(Plot_array(Mkr_bin,2)-Offset)/Scale_factor
4920      END IF
4930      SET LOCATOR Mkr_bin,MAX(Y_min,MIN(Y_max,Y))
4940      IF Mkr_bin=Last_marker AND Old_dummy=Dummy THEN    !not moving
4950        GOSUB Disp_mkr
4960      ELSE
4970        SET ECHO Plot_array(Mkr_bin,1),MAX(Y_min,MIN(Y_max,Y))
4980      END IF
4990      Old_dummy=Dummy
5000      Last_marker=Mkr_bin
5010      ENABLE 
5020    UNTIL FNUser_key_press
5030    DISP 
5040    IF FNUser_check_key>3 THEN SET ECHO Start_bin-10.0*(Stop_bin-Start_bin),Y_min
5050    Disp_set_offs0(1.0*Mkr_bin,"X")
5060    Disp_set_offs0(Dummy,"Y_ABS")
5070    Disp_set_offs0(Dummy-(Plot_array(Mkr_bin,2)-Offset)/Scale_factor,"Y")
5080    !move the marker off of the screen unless the "Move marker" softkey
5090    SUBEXIT
5100 Disp_mkr:  !------------------------------------------------
5110   !Given marker_bin and Y, displays marker value
5120    Y_temp=Y-FNDisp_get_curs("Y_ABS")
5130    Mkr_bin_temp=Mkr_bin-FNDisp_get_curs("X")
5140    IF Do_log_y THEN !Plot_data has been logged, need to un-log
5150      CALL Plot_eng_format(10^Y_temp,0,Y$,"",8,Y_prefix$)
5160    ELSE
5170      IF POS(UPC$(Y_units$),"DB") THEN !special case for dB
5180        Y$=""
5190        OUTPUT Y$ USING "#,DDDD.DDD";Y_temp
5200      ELSE
5210        CALL Plot_eng_format(Y_temp,0,Y$,"",8,Y_prefix$)
5220      END IF
5230    END IF
5240    X=X_min+(Mkr_bin_temp-Start_bin)*(Per_bin_x)
5250    CALL Plot_eng_format(X,0,X$,"",8,X_prefix$)
5260    D_line$=X$&X_prefix$&" "&X_units$
5270    D_line$=D_line$&RPT$(" ",20-LEN(D_line$))
5280    D_line$=D_line$&Y$&Y_prefix$&" "&Y_units$
5290    IF Y_temp<>Y OR Mkr_bin<>Mkr_bin_temp THEN D_line$=D_line$&"   ***  RN ***"
5300    DISP D_line$
5310    RETURN 
5320  SUBEND
5330  ! PAGE -> 
5340  !************************************************************************
5350 Plot_move_mkr:SUB Plot_move_mkr(Plot_array(*),X_units$,X_min,X_max,To$)
5360  ! This subprogram is called from the marker menu when a "Marker to ?"
5370  ! soft key is pressed.
5380  ! It's output is a side effect:  It may modify the current marker
5390  ! bin number stored in common.
5400  !---------------------------------------------------------------------
5410    COM /Plot_mkr/ INTEGER Mkr_bin  !for memory between calls
5420    DIM New_entry$[100]
5430    INTEGER X,Start_bin,Stop_bin
5440    Start_bin=BASE(Plot_array,1)
5450    Stop_bin=BASE(Plot_array,1)+SIZE(Plot_array,1)-1
5460    Per_bin_x=(X_max-X_min)/(Stop_bin-Start_bin)
5470    SELECT To$
5480    CASE "MIN"
5490      GOSUB To_min
5500    CASE "MAX"
5510      GOSUB To_max
5520    CASE ELSE
5530      GOSUB To_x
5540    END SELECT
5550    SUBEXIT
5560 To_x:  !-----------------------------------------------------------
5570    IF X_units$<>"" THEN 
5580      DISP "Move marker: X axis value in ";X_units$;
5590    ELSE
5600      DISP "Move marker: X axis value ";
5610    END IF
5620    LINPUT New_entry$
5630    DISP 
5640    IF LEN(New_entry$)>0 THEN 
5650      ON ERROR GOTO Nevermind
5660      Mkr_bin=MIN(Stop_bin,(VAL(New_entry$)-X_min)/Per_bin_x+Start_bin)
5670 Nevermind:OFF ERROR 
5680    END IF
5690    RETURN 
5700 To_min:        !-------------------------------------------------------
5710    FOR X=Start_bin TO Stop_bin
5720      IF Plot_array(X,2)<Plot_array(Mkr_bin,2) THEN 
5730        Mkr_bin=X
5740      END IF
5750    NEXT X
5760    RETURN 
5770 To_max:        !-------------------------------------------------------
5780    FOR X=Start_bin TO Stop_bin
5790      IF Plot_array(X,2)>Plot_array(Mkr_bin,2) THEN 
5800        Mkr_bin=X
5810      END IF
5820    NEXT X
5830    RETURN 
5840  SUBEND
5850  ! PAGE -> 
5860  !************************************************************************
5870  DEF FNPlot_have_color
5880  !This function returns 1 if color is available
5890    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
5900    RETURN Have_color
5910  FNEND
5920  SUB Plot_set_color(Use_color)
5930  !This subprogram turn on and off color by setting a flag in common.
5940    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color_c
5950    IF (Use_color<>0) AND FNPlot_have_color THEN 
5960      Use_color_c=1
5970    ELSE
5980      Use_color_c=0
5990    END IF
6000  SUBEND
6010  DEF FNPlot_use_color
6020  !This function returns 1 if color is turned on.
6030    COM /Plot_config/ X_pixels,Y_pixels,Have_color,Use_color
6040    RETURN Use_color
6050  FNEND
6060  ! PAGE -> 
6070  !************************************************************************
6080 Plot_eng_format:SUB Plot_eng_format(Value1,Value2,V1$,V2$,Digits,Prefix$)
6090  !This subprogram converts 2 values to engineering format.
6100  !To use it with only one value, set the other to zero
6110  !INPUTS:  Value1, Value2:  values in fundamental units (Hz).
6120  !         Digits:  Number of digits to round to.
6130  !OUTPUTS: V1$, V2$: Strings returning the rounded output.
6140  !         Prefix$: Engineering format prefix for units.
6150  !------------------------------------------------------------------------
6160    Max_value=DROUND(MAX(ABS(Value1),ABS(Value2)),Digits)
6170    IF Max_value>10^(-15) THEN  !check for log of zero
6180      SELECT LGT(Max_value)
6190      CASE >=6
6200        Exponent=6
6210        Prefix$="M"
6220      CASE 3 TO 6
6230        Exponent=3
6240        Prefix$="K"
6250      CASE 0 TO 3
6260        Exponent=0
6270        Prefix$=""
6280      CASE -3 TO 0
6290        Exponent=-3
6300        Prefix$="m"
6310      CASE -6 TO -3
6320        Exponent=-6
6330        Prefix$="u"
6340      CASE -9 TO -6
6350        Exponent=-9
6360        Prefix$="n"
6370      CASE <-9
6380        Exponent=-12
6390        Prefix$="p"
6400      END SELECT
6410    ELSE
6420      Exponent=0
6430      Prefix$=""
6440    END IF
6450    V1$=VAL$(DROUND(Value1/10^Exponent,Digits))
6460    V2$=VAL$(DROUND(Value2/10^Exponent,Digits))
6470  SUBEND
6480  ! PAGE -> 
6490  !************************************************************************
6500 Plot_bold_label:SUB Plot_bold_label(Char_size,L$)
6510  !This subprogram plots a bold label with CSIZE Char_size.
6520    INTEGER N,Max_n
6530    WHERE X,Y
6540    CSIZE Char_size
6550    Max_n=(Char_size/FNPlot_good_csize)-1
6560    X_step=FNPlot_x_pixel*.999
6570    Y_step=FNPlot_y_pixel*.999
6580    FOR N=0 TO Max_n
6590      MOVE X+Max_n*X_step,Y+N*Y_step
6600      LABEL L$
6610    NEXT N
6620    FOR N=0 TO Max_n
6630      MOVE X+N*X_step,Y
6640      LABEL L$
6650    NEXT N
6660    FOR N=0 TO Max_n
6670      MOVE X+N*X_step,Y+Max_n*Y_step
6680      LABEL L$
6690    NEXT N
6700    FOR N=Max_n TO 0 STEP -1   !want to do X+0,Y+0 last for pen position
6710      MOVE X,Y+N*Y_step
6720      LABEL L$
6730    NEXT N
6740  SUBEND
6750  ! PAGE -> 
6760  !************************************************************************
6770 Plot_make_x:SUB Plot_make_x(Plot_array(*),Do_log_x,X_min,X_max)
6780   !This subprogram fills the X elements of Plot_array(*) for the PLOT
6790   !command. If the x axis is to be LOGed, it is done here.
6800   !
6810   !INPUTS:  Do_log_x:    Flag 0: linear x axis,  <>0 : log x axis
6820   !         X_min,X_max: X axis bounds in real world units.
6830   !OUTPUTS: Plot_array(*):  2D array of xy points ready for PLOT command.
6840   !                    Plot_array(*,1) = x = bin numbers for linear plots,
6850   !                                  "distorted" bin numbers for log plots.
6860   !                    Plot_array(*,2) = y = y values. not changed.
6870   !
6880   !-----------------------------------------------------------------
6890    INTEGER Bin,Start_bin,Stop_bin
6900    Start_bin=BASE(Plot_array,1)
6910    Stop_bin=SIZE(Plot_array,1)+Start_bin-1
6920    IF Do_log_x THEN          ! x axis is logged
6930      GOSUB Do_log
6940    ELSE
6950      GOSUB Do_lin
6960    END IF
6970    SUBEXIT
6980 Do_lin:    !--------------------------------------------------------
6990    !re- compute only if necessary
7000    IF (Plot_array(Start_bin+1,1)<>Start_bin+1) OR (Plot_array(Stop_bin,1)<>Stop_bin) THEN 
7010      FOR Bin=Start_bin TO Stop_bin
7020        Plot_array(Bin,1)=Bin
7030      NEXT Bin
7040    END IF
7050    RETURN 
7060 Do_log:    !--------------------------------------------------------
7070    !The x-axis log works like this:
7080    !The X elements of Plot_array(*) that are usually bin numbers for
7090    !linear plots are "distorted" into log sequence.  The distortion
7100    !is such that the first and last bins are not changed.  In other
7110    !words Plot_array(Start_bin,1)=Start_bin  and
7120    !Plot_array(Stop_bin,1)=Stop_bin,  but everything between will
7130    !be different.  The formula for the distortion is
7140    !    Plot_array(Bin,1) = A*LGT(Freq) + B
7150    !where A and B are figured below, and Freq is real world X value
7160    !of the Bin.
7170    !
7180    A=(Stop_bin-Start_bin)/LGT(X_max/X_min)
7190    B=Start_bin-A*LGT(X_min)
7200    Per_bin_x=(X_max-X_min)/(Stop_bin-Start_bin)
7210    !
7220    !Comput new values only if old values are incorrect.
7230    IF ABS(Plot_array(Start_bin+1,1)-(A*LGT(X_min+Per_bin_x)+B))>1.E-4 OR (Plot_array(Stop_bin,1)<>Stop_bin) THEN 
7240      FOR Bin=Start_bin TO Stop_bin-1
7250        Plot_array(Bin,1)=A*LGT(X_min+(Bin-Start_bin)*Per_bin_x)+B
7260      NEXT Bin
7270      Plot_array(Stop_bin,1)=Stop_bin
7280    END IF
7290    RETURN 
7300  SUBEND
7310  ! PAGE -> 
7320  !************************************************************************
7330 Plot_make_y:SUB Plot_make_y(Data_buffer(*),Data_header(*),Plot_array(*),Buf_num,Start_bin,Stop_bin_r,Do_log,Offset,Scale_factor)
7340   !This subprogram converts Data_buffer(*) into Plot_array(*) for the PLOT
7350   !command. If the data is to be LOGed, it is done here.
7360   !There is a CSUB version that does the same operation much quicker.
7370   !The CSUB should be above this, so the CSUB will be used.
7380   !
7390   !INPUTS: Data_buffer(*):  2D array of y data blocks.  This sub only
7400   !                    operates on one block, Data_buffer(Buf_num,*).
7410   !        Data_header(*):  2D array of header info for y data blocks.
7420   !        Buf_num:    Which buffer of Data_buffer.
7430   !        Start_bin, Stop_bin:  Data_buffer index range to plot.
7440   !OUTPUTS: Plot_array(*):  2D array of xy points ready for PLOT command.
7450   !                    Plot_array(*,1) = x, not changed.
7460   !                    Plot_array(*,2) = y = y values.
7470   !        Offset:  Offset yet to be subtracted from y values.
7480   !        Scale_factor:  Scale factor yet to be applied to y values.
7490   !
7500   ! For maximum speed, this sub has a separate DO loop for each case.
7510   !-----------------------------------------------------------------
7520    INTEGER X,Stop_bin
7530    Stop_bin=Stop_bin_r
7540    Offset=Data_header(Buf_num,1)
7550    Scale_factor=Data_header(Buf_num,2)
7560    Log_multiplier=Data_header(Buf_num,4)
7570    IF Do_log THEN Log_multiplier=1
7580    IF Log_multiplier=0 THEN         !linear
7590      FOR X=Start_bin TO Stop_bin
7600        Plot_array(X,2)=Data_buffer(Buf_num,X)
7610      NEXT X
7620    ELSE                              !do log
7630      ON ERROR GOTO No_zero
7640      Zero_value=LGT((Data_header(Buf_num,5)-Offset)/Scale_factor)
7650 No_zero:OFF ERROR 
7660      IF Log_multiplier>0 THEN        !positive log multiplier
7670        FOR X=Start_bin TO Stop_bin
7680          IF Data_buffer(Buf_num,X)>0 THEN 
7690            Plot_array(X,2)=LGT((Data_buffer(Buf_num,X)-Offset)/Scale_factor)
7700          ELSE
7710            Plot_array(X,2)=Zero_value
7720          END IF
7730        NEXT X
7740        !zero offset since it has been applied, change scale factor
7750        Offset=0
7760        Scale_factor=1/Log_multiplier
7770      ELSE                            !negative log multiplier
7780        FOR X=Start_bin TO Stop_bin
7790          IF Data_buffer(Buf_num,X)>0 THEN 
7800            Plot_array(X,2)=-LGT((Data_buffer(Buf_num,X)-Offset)/Scale_factor)
7810          ELSE
7820            Plot_array(X,2)=-Zero_value
7830          END IF
7840        NEXT X
7850        Offset=0
7860        Scale_factor=-1/Log_multiplier
7870      END IF                          !log multiplier sign
7880    END IF
7890  SUBEND
7900  ! PAGE -> 
7910  !************************************************************************
7920 Plot_mkr_bin:DEF FNPlot_mkr_bin
7930    COM /Plot_mkr/ INTEGER Mkr_bin
7940    RETURN Mkr_bin
7950  FNEND