10!  OUTPUT 2 USING "#,K";"<lf>INDENT<cr><lf>RE-STORE ""DISP""<cr>"
20    !
21  !Rev 1.1 Changes:  Corrected #1 in SUB Disp_put_titles
30  !  EDIT Test_prog
40  !  EDIT Disp_disp
50  !  EDIT Disp_spread_set
60  !  EDIT Disp_spread
70  !  EDIT Disp_plot_set
80  !  EDIT Disp_log_set
90  !  EDIT Disp_plot_axis
100 !  EDIT Disp_plot_data
110 !  EDIT Disp_do_mkr
120 !  EDIT Disp_put_traces
130 !  EDIT Disp_put_titles
140 !  EDIT Disp_Choice
150 !  EDIT Disp_num_plots
160 !  EDIT Disp_update_com
170 !  EDIT Disp_reset
180 !  EDIT Disp_save
190 !  EDIT Disp_load
200 !  EDIT Disp_store_tr
210 !  EDIT Disp_zap
220 !  EDIT Disp_recall_tr
230 !
240 Disp_doc: !  17-Jun-86
250 ! ******************************************************************
260 !               DISPLAY (Disp_) FILE DESCRIPTION
270 ! Subprograms in the DISP file are called by application programs
280 ! to display measurement data  graphically.  The display spread sheet allows
290 ! the user to select and scale traces.  The plot and marker subprograms
300 ! plot data on the CRT.  The lower-level graphics commands are done by
310 ! subprograms in the PLOT file, which DISP subprograms call.
320 !------------------------------------------------------------------
330 !
340 ! Sequence of Events:
350 !   1.  Disp_Disp is called at initialization.
360 !   2.  Disp_spread_set is called to define the display spread sheet.
370 !   3.  Disp_spread is called to allow the user to view and change the
380 !                   display spread sheet.
390 !   4.  FNDisp_choice and FNDisp_num_plots may be called to return display
400 !                   spread sheet information.
410 !   5.  Disp_plot_set is called to define plot parameters.
420 !   6.  Disp_plot_axis is called to plot axis, grids, and labels.
430 !   7.  Measurement data is collected.
440 !   8.  Disp_plot_data is called to plot the data.
450 !   9.  Disp_do_mkr may be called to turn on the marker.
460 !
470 !If the display spread sheet is not used steps 2 and 3 can be omitted and
480 !Disp_put_traces and Disp_put_titles can be called instead.
490 !
500 ! Plot setup are defined by the pass parameters to the
510 ! Disp_put_traces, Disp_put_titles, Disp_log_set, and Disp_plot_set
520 ! subprograms.  The plot setup are "remembered" and used at a later time.
530 !
540 ! The data to be plotted is passed into the Disp_plot_data and
550 ! Disp_do_mkr subprograms using a two arrays,
560 ! Data_buffer(*) and Data_header(*).  The format of Data_buffer(*) is:
570 !
580 ! The format of Data_buffer(*) is:
590 !       Data_buffer( 1:Num_blocks, 0:record_length-1) Array of the floating pt
600 !                      data. Could be time records, freq responses or
610 !                      whatever.  Record_length will usually be
620 !                      something like BSIZ / 2
630 !
640 ! The format of Data_header is:
650 !       Data_header( 1:Num_blocks, 1:10)  Array of values that are common
660 !                      to all elements in a block of Data_buffer(*).
670 !                      Elements of Data_header are defined as follows:
680 !
690 !        (Block_num,1) The offset to be applied.  Defined as the
700 !                      value of an element of Data_buffer would have
710 !                      if it were 0.000.  The offset is done before
720 !                      the scale factor below.  In other words,
730 !                      this value will be subtracted from each element
740 !                      of Data_buffer.
750 !
760 !        (Block_num,2) The scale factor to be applied.  Defined as the
770 !                      value of an element of Data_buffer would have
780 !                      if it were 1.000, after the offset had been applied.
790 !                      In other words, Data_buffer elements will be
800 !                      divided by this to get real-world units.
810 !
820 !        (Block_num,3) Overload information.  If non zero "OVLD"
830 !                      will appear on the plot.
840 !
850 !        (Block_num,4) Logarithm multiplier.  If non zero, the base 10
860 !                      log is taken of each element in Data_buffer and
870 !                      the result is multiplied by this number to get
880 !                      displayed units.  The log is applied after
890 !                      the offset and scale factor.  If =0 then no
900 !                      log is done.  Although the trace shape will be the same,
910 !                      this is not the same as setting the Do_log_y flag.
920 !
930 !        (Block_num,5) Log of zero value.  This is the value to use
940 !                      in place of zero to keep the log function from
950 !                      blowing up.  It is scaled the same as other
960 !                      Data_buffer elements, so it will be logged.
970 !
980 !        (Block_num,6) Average  information.  If non zero "Avg <n>"
990 !                      will appear on the plot.
1000!
1010!        (Block_num,7) Real time information. If non zero "RT" will
1020!                      appear on the plot.
1030!
1040!        (Block_num,8:10)  undefined, should be =0
1050!
1060!            Summary of header math:
1070!              IF H(4)=0  :           (Data_buffer(*)-H(1)) /H(2)
1080!              IF H(4)<>0 : H(4)*LGT( (Data_buffer(*)-H(1)) /H(2) )
1090!              IF H(4)<>0 and Data_buffer(i)<=0 : H(4)*LGT(H(5)-H(1)/H(2))
1100!
1110! ******************************************************************
1120!
1130!
1140 Test_prog: !---------------------------------------------------------
1150  !  LOADSUB ALL FROM "USER"
1160  !  LOADSUB ALL FROM "LIB"
1170  !  LOADSUB ALL FROM "PLOT"
1180  !
1190  !  <PLACE TEST CODE HERE>
1200  CALL Disp_disp
1210  CALL User_user
1220  CALL Plot_plot
1230  Rl=512
1240  Num_bufs=8
1250  !
1260  !
1270  Channel_name=1    !constants used to index Title$(*), Choices$(*), etc
1280  Trace_type=2
1290  !
1300  DIM Title$(1:2,1:2)[40]
1310  Title$(Channel_name,1)="Channel"
1320  Title$(Channel_name,2)="Name"
1330  Title$(Trace_type,1)="Trace"
1340  Title$(Trace_type,2)="Type"
1350  !
1360  DIM Prompt$(1:2)[80]
1370  Prompt$(Channel_name)="Channel name"
1380  Prompt$(Trace_type)="Trace type: (Time or Freq)"
1390  !
1400  DIM Col_width(1:2)
1410  Col_width(Channel_name)=16
1420  Col_width(Trace_type)=12
1430  !
1440  DIM Choices$(1:2,1:64)[40]
1450  MAT Choices$= ("")
1460  Choices$(Trace_type,1)="Time"
1470  Choices$(Trace_type,2)="Freq"
1480  FOR I=1 TO 4
1490    Choices$(Channel_name,I)="Input "&VAL$(I)
1500  NEXT I
1510  !
1520  DISP "calling spread_set"
1530  CALL Disp_spread_set(Title$(*),Prompt$(*),Col_width(*),Choices$(*))
1540  !
1550  ALLOCATE Data_buffer(1:Num_bufs,0:Rl-1),Data_header(1:Num_bufs,1:10)
1560  !
1570  !
1580  DISP "filling data_buffer"
1590  FOR B=1 TO Num_bufs
1600    Data_header(B,1)=0    !offset
1610    Data_header(B,2)=1    !gain
1620    Data_header(B,3)=1    !overload
1630    Data_header(B,4)=0    !LOG
1640    Data_header(B,6)=2    !average
1650    Data_header(B,7)=0    !real time
1660    FOR I=0 TO Rl-1
1670      Data_buffer(B,I)=I/Rl
1680    NEXT I
1690  NEXT B
1700  !
1710  !
1720  ALLOCATE X_units$(1:16)[10],Y_units$(1:16)[10],Start_x(1:16),Per_bin_x(1:16),Start_bin(1:16),Num_bins(1:16),Y_def_max(1:16),Y_def_min(1:16)
1730  ALLOCATE Plot_to_buf(1:16),Do_log_x(1:16),Do_log_y(1:16)
1740  ON KEY 1 LABEL FNUser_keylabel$("DISPLAY") CALL User_key1isr
1750  ON KEY 6 LABEL FNUser_keylabel$("MAIN") CALL User_key6isr
1760  GOSUB Update
1770  LOOP
1780    DISP "calling spread"
1790    CALL Disp_spread(Modified,Major_mod)
1800    Dummy=FNUser_get_key
1810    IF Modified THEN 
1820      GOSUB Update
1830    END IF
1840    DISP "calling plot_data"
1850    CALL Disp_plot_axis
1860    CALL Disp_plot_data(Data_buffer(*),Data_header(*))
1870    CALL Disp_do_mkr(Data_buffer(*),Data_header(*),0)
1880    Dummy=FNUser_get_key
1890  END LOOP
1900  STOP
1910 Update: !---------------------------------------------------------
1920  Num_plots=FNDisp_num_plots
1930  FOR Plot_num=1 TO Num_plots     !loop for each plot selected
1940      !
1950    Trace_type_num=FNDisp_choice(Plot_num,Trace_type)
1960    Channel_name_n=FNDisp_choice(Plot_num,Channel_name)
1970      !
1980      !figure out which buffer the data will be in.  Assuming the buffer is
1990      ! input1 time, input 1 Log Mag, input 2 time, .... etc, then :
2000    Plot_to_buf(Plot_num)=2*Channel_name_n+Trace_type_num-2
2010      !
2020      !setup plot labeling depending on plot type
2030    SELECT Choices$(Trace_type,Trace_type_num)
2040    CASE "Time"
2050      X_units$(Plot_num)="Sec"
2060      Y_units$(Plot_num)="Volt"
2070      Start_x(Plot_num)=0
2080      Per_bin_x(Plot_num)=2/262144.0
2090      Start_bin(Plot_num)=0
2100      Num_bins(Plot_num)=Rl
2110      Y_def_max(Plot_num)=1
2120      Y_def_min(Plot_num)=-1
2130      Do_log_y(Plot_num)=0
2140      Do_log_x(Plot_num)=0
2150    CASE "Freq"
2160      X_units$(Plot_num)="Hz"
2170      Y_units$(Plot_num)=""
2180      Start_x(Plot_num)=0
2190      Per_bin_x(Plot_num)=65536/Rl
2200      Start_bin(Plot_num)=0
2210      Num_bins(Plot_num)=Rl
2220      Y_def_max(Plot_num)=1
2230      Do_log_x(Plot_num)=Plot_num MOD 2
2240          !
2250          !or, for example
2260  !       Input_name$=Choices$(Channel_name,Channel_name_n)
2270  !       Y_def_max(Plot_num)=VAL(FNInp_rsp$(Input_name$,"RNG"))
2280          !
2290      Y_def_min(Plot_num)=-1
2300    CASE ELSE
2310      CALL User_stop("")
2320    END SELECT
2330  NEXT Plot_num
2340  DISP "calling plot_set"
2350  CALL Disp_plot_set(Plot_to_buf(*),X_units$(*),Y_units$(*),Start_x(*),Per_bin_x(*),Start_bin(*),Num_bins(*),Y_def_max(*),Y_def_min(*))
2360  CALL Disp_log_set(Do_log_x(*),Do_log_y(*))
2370  RETURN 
2380!
2390!
2400  END
2410  ! PAGE -> 
2420  !************************************************************************
2430 Disp_disp:SUB Disp_disp
2440    !This subprogram defines and initializes all common used by the DISP
2450    !file subprograms.  The size of the recalled trace buffer is defined
2460    !here and can be modified to suit application or memory requirements.
2470    !
2480    !These common blocks give the display spread sheet memory:
2490    COM /Disp_spread1/ Box$(1:10,1:17)[45],Row,Col,Start_row
2500    COM /Disp_spread2/ Title$(1:10,0:2)[45],Prompt$(1:10)[80],Col_width(1:10)
2510    COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
2520    COM /Disp_spread4/ Choices$(1:6,1:64)[45],Num_choices(1:6)
2530    COM /Disp_choice/ Plot_choice(1:16,1:6)
2540    !
2550    !
2560    !These common blocks "store" plot setups.  Values are set by subprograms
2570    !like Disp_plot_set, and used by subprograms like Disp_plot_axis.
2580    COM /Disp_num_plots/ Num_live_plots,Num_r_plots
2590    COM /Disp_titles/ Plot_titles$(1:16)[45]
2600    COM /Disp_y/ Y_max$(1:16)[20],Y_min$(1:16)[20]
2610    COM /Disp_buf/ Plot_to_buf(1:16),Start_bin(1:16),Num_bins(1:16)
2620    COM /Disp_units/ X_units$(1:16)[10],Y_units$(1:16)[10]
2630    COM /Disp_window/ X_min(1:16),X_max(1:16),Y_min(1:16),Y_max(1:16)
2640    COM /Disp_log/ Do_log_x(1:16),Do_log_y(1:16)
2650    COM /Disp_mkr/ Mkr_plot
2660    COM /Disp_misc/ Y_units_len,Plots_done,R_plots_done
2670    !
2680    !
2690    !The size of the Recall_buf can be changed here. This determines
2700    !the number of traces that can be recalled and their maximum size.
2710    COM /Disp_recall/ Recall_buf(1:2,1:4096),Recall_head(1:2,1:10)  !2 big ones
2720  ! COM /Disp_recall/ Recall_buf(1:1,1:1024),Recall_head(1:1,1:10)  !smaller one
2730    !
2740    !These common blocks store other recalled trace info and should not
2750    !be changed.
2760    COM /Disp_recall1/ R_x_units$(1:16)[10],R_y_units$(1:16)[10],R_num_bins(1:16)
2770    COM /Disp_recall2/ R_x_min(1:16),R_x_max(1:16),R_y_def_min(1:16),R_y_def_max(1:16)
2780    COM /Disp_recall3/ R_do_log_x(1:16),R_do_log_y(1:16)
2790    COM /Disp_recall4/ Plot_to_r_buf(1:16)
2800    !
2810    !C_plot_array is saved in common to avoid re-computing the x axis.
2820    COM /Disp_plot_array/ C_plot_array(1:1024,1:2),C_p_size
2830    C_p_size=1024
2840    !
2850    Num_recall_rows=SIZE(Recall_buf,1)   !for spread sheet
2860  SUBEND
2870  !************************************************************************
2880 Disp_spread_set:SUB Disp_spread_set(Ex_title$(*),Ex_prompt$(*),Ex_col_width(*),Ex_choices$(*))
2890  !This sub sets up the display spread sheet.  It should be called
2900  !before Disp_spread and whenever there is a configuration change.
2910  !It defines the spread sheet titles, etc which are stored in COM.
2920  !Columns for "Active" "Y min" and "Y max" are standard, from 1 to 6
2930  !other columns are defined by by the calling program.  Passed arrays
2940  !in should be dimensioned to the number of columns needed, up to 6.
2950!       Ex_title$(1:6,1:2)[45]  Two lines of titles for the columns.
2960!       Ex_prompt$(1:6)[80] Prompts for the columns.
2970!       Ex_col_width(1:6) Width of the columns.
2980!       Ex_choices$(1:6,1:64)[45] An array of possible choices for each
2990!                      column.
3000  !
3010    COM /Disp_spread1/ Box$(*),Row,Col,Start_row
3020    COM /Disp_spread2/ Title$(*),Prompt$(*),Col_width(*)
3030    COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
3040    COM /Disp_spread4/ Choices$(*),Num_choices(*)
3050 !
3060    Num_categories=SIZE(Ex_title$,1)  !number of externally defined columns
3070    Max_col=Num_categories+4       !4 for num, active, y min, y max
3080    !
3090    !
3100    !For each category, count the number of choices
3110    REDIM Num_choices(1:Num_categories)
3120    FOR Category_num=1 TO Num_categories
3130      Choice_num=0
3140      REPEAT
3150        Choice_num=Choice_num+1
3160      UNTIL (Ex_choices$(Category_num,Choice_num)="") OR (Choice_num=SIZE(Ex_choices$,2))
3170      IF Ex_choices$(Category_num,Choice_num)="" THEN Choice_num=Choice_num-1
3180      Num_choices(Category_num)=Choice_num
3190    NEXT Category_num
3200    !
3210    !copy list of choices into common
3220    REDIM Choices$(1:Num_categories,1:MAX(Num_choices(*)))
3230    FOR Category_num=1 TO Num_categories
3240      FOR Choice_num=1 TO Num_choices(Category_num)
3250        Choices$(Category_num,Choice_num)=Ex_choices$(Category_num,Choice_num)
3260      NEXT Choice_num
3270    NEXT Category_num
3280    !
3290    !figure out how many rows of live (not recalled) traces should be displayed
3300    Num_live_rows=1
3310    FOR Category_num=1 TO Num_categories
3320      Num_live_rows=Num_live_rows*Num_choices(Category_num)
3330    NEXT Category_num
3340    Num_live_rows=MIN(Num_live_rows,16)
3350    Max_row=1+Num_live_rows+Num_recall_rows    !+1 for "All" line
3360    REDIM Box$(1:Max_col,1:Max_row)
3370    !
3380    !define constants for other columns
3390    Active_col=2
3400    Y_min_col=3+Num_categories
3410    Y_max_col=4+Num_categories
3420    !
3430    !re-DIM arrays in common so they can be indexed by column instead
3440    !of category_num
3450    REDIM Num_choices(3:2+Num_categories)
3460    REDIM Choices$(3:2+Num_categories,1:MAX(Num_choices(*)))
3470 !
3480 ! These data statements define the setup and titles for each column
3490 !
3500 !   col_width  title1         title2      Prompt
3510 !   ---------  ----------     ----------  --------------------
3520    DATA    5,     "Trace",    "Num",     ""
3530    DATA    4,     "Act-",     "ive",     "Trace active: (Yes or No)"
3540  !externally defined columns show up here
3550    DATA    9,     "Y Axis",     "Min",      "Y Axis minimum: (value or ""Default"")"
3560    DATA    9,     "Y Axis",     "Max",      "Y Axis maximum: (value or ""Default"")"
3570 !
3580 !
3590 !read spread sheet setup into arrays
3600    MAT Col_width= (0)
3610    Title$(1,0)="DISPLAY SETUP"
3620    FOR C=1 TO 2
3630      READ Col_width(C),Title$(C,1),Title$(C,2),Prompt$(C)
3640    NEXT C
3650    FOR C=3 TO 2+Num_categories
3660      Col_width(C)=Ex_col_width(C-2)
3670      Title$(C,1)=Ex_title$(C-2,1)
3680      Title$(C,2)=Ex_title$(C-2,2)
3690      Prompt$(C)=Ex_prompt$(C-2)
3700    NEXT C
3710    FOR C=Num_categories+3 TO Max_col
3720      READ Col_width(C),Title$(C,1),Title$(C,2),Prompt$(C)
3730    NEXT C
3740    !
3750    !set rows to initial values
3760    CALL Disp_reset
3770    !
3780    !copy Box$ to other common blocks
3790    CALL Disp_update_com
3800    !
3810  SUBEND
3820  ! PAGE -> 
3830  !************************************************************************
3840 Disp_spread:SUB Disp_spread(Modified,OPTIONAL Major_mod)
3850  !This subprogram is the display spread sheet, called when the
3860  !DISPLAY SETUP softkey is pressed.  For up to 16 "live" traces, it allows the
3870  !user to make the trace active, change Y axis scaling, or change one
3880  !or more application-dependent items.  It also allows the user to recall
3890  !a previously stored trace into one of the recall buffers.  <Modified> is
3900  !is set to 1 if any changes were made.  <Major_mod> is set to 1 if
3910  !any changes were made to any of the spread sheet columns
3920  !other than Y axis scaling.
3930    COM /Disp_spread1/ Box$(*),Row,Col,Start_row
3940    COM /Disp_spread2/ Title$(*),Prompt$(*),Col_width(*)
3950    COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
3960    COM /Disp_spread4/ Choices$(*),Num_choices(*)
3970 !
3980    DIM New_entry$[160]
3990    Max_row=SIZE(Box$,2)
4000 !
4010    GOSUB Label_keys
4020    CALL User_clr_scr
4030 !Now call spread sheet.  It returns with New_entry$ and Row and Col
4040    Done=0
4050    Modified=0
4060    Major_mod1=0
4070    REPEAT
4080      CALL User_spread(Box$(*),Title$(*),Prompt$(*),New_entry$,Col_width(*),2,Col,Row,Start_row)
4090      SELECT FNUser_check_key
4100      CASE 0   !no key pressed, must be a New_entry$ for Box
4110        GOSUB New_entry
4120      CASE 5         !the Reset key
4130        Dummy=FNUser_get_key
4140        CALL Disp_reset
4150        Modified=1
4160        Major_mod1=1
4170      CASE 6         !"Color" softkey
4180        Dummy=FNUser_get_key
4190        IF FNPlot_have_color THEN 
4200          CALL Plot_set_color(NOT FNPlot_use_color)
4210          GOSUB Label_keys
4220        ELSE
4230          BEEP 651,.03
4240        END IF
4250      CASE 7         !Prev
4260        Dummy=FNUser_get_key
4270        GOSUB Prev_choice
4280      CASE 8         !next
4290        Dummy=FNUser_get_key
4300        GOSUB Next_choice
4310      CASE ELSE      !a softkey but not one of mine, so exit
4320        Done=1
4330      END SELECT
4340    UNTIL Done
4350    CALL User_clr_scr
4360    IF Modified THEN CALL Disp_update_com
4370    IF NPAR>1 THEN Major_mod=Major_mod1
4380    SUBEXIT
4390 New_entry:         !------------------------------------------------
4400   !acts on new_entry from spread_sheet
4410    New_entry$=UPC$(TRIM$(New_entry$))
4420    IF New_entry$[1,1]="""" THEN New_entry$=TRIM$(New_entry$[2]) !delete "
4430    IF New_entry$<>"" THEN 
4440      SELECT Col
4450      CASE Active_col
4460        Modified=1
4470        Major_mod1=1
4480        SELECT New_entry$[1,1]
4490        CASE "Y","*"
4500          SELECT Row
4510          CASE 1    !All row
4520            FOR R=2 TO Num_live_rows+1
4530              Box$(Col,R)="*"
4540            NEXT R
4550          CASE <=Num_live_rows+1
4560            Box$(Col,Row)="*"
4570          CASE >Num_live_rows+1    !recalled trace
4580            GOSUB Recall_trace
4590          END SELECT
4600        CASE "N"
4610          SELECT Row
4620          CASE 1
4630            FOR R=2 TO Max_row
4640              Box$(Col,R)=""
4650            NEXT R
4660            FOR R=Num_live_rows+2 TO Max_row
4670              Box$(Active_col+1,R)="Recall trace "&VAL$(R-Num_live_rows-1)
4680            NEXT R
4690          CASE <=Num_live_rows+1
4700            Box$(Col,Row)=""
4710          CASE >Num_live_rows+1    !recalled trace
4720            GOSUB Cancel_recall
4730          END SELECT
4740        CASE ELSE
4750          BEEP 200,.1
4760        END SELECT
4770      CASE Active_col+1 TO Y_min_col-1  !application dependent cols
4780        Modified=1
4790        Major_mod1=1
4800        IF Row<=Num_live_rows+1 THEN 
4810          CALL Lib_match2(New_entry$,Choices$(*),Col,Found,Choice_num)
4820          IF Found THEN 
4830            IF Row=1 THEN 
4840              FOR R=2 TO Num_live_rows+1
4850                Box$(Col,R)=Choices$(Col,Choice_num)
4860              NEXT R
4870            ELSE
4880              Box$(Col,Row)=Choices$(Col,Choice_num)
4890            END IF
4900          ELSE
4910            BEEP 200,.1
4920          END IF
4930        ELSE   !row is recalled traces
4940          CALL User_error("Sorry, you can not modify this box on recalled traces.")
4950        END IF
4960      CASE Y_min_col,Y_max_col
4970        Modified=1
4980        IF New_entry$[1,1]="D" THEN 
4990          IF Row=1 THEN 
5000            FOR R=2 TO Max_row
5010              Box$(Col,R)="Default"
5020            NEXT R
5030          ELSE
5040            Box$(Col,Row)="Default"
5050          END IF
5060        ELSE
5070          ON ERROR GOTO Not_a_number
5080          Dummy=VAL(New_entry$)
5090          IF Row=1 THEN 
5100            FOR R=2 TO Max_row
5110              Box$(Col,R)=New_entry$
5120            NEXT R
5130          ELSE
5140            Box$(Col,Row)=New_entry$
5150          END IF
5160          OFF ERROR 
5170          GOTO Ok
5180 Not_a_number:OFF ERROR 
5190          DISP ERRM$
5200          BEEP 200,.1
5210          WAIT 2
5220          DISP 
5230 Ok:        !
5240        END IF
5250      END SELECT
5260    END IF
5270    RETURN 
5280 Prev_choice:  !--------------------------------------------------
5290    SELECT Col
5300    CASE Active_col
5310      Modified=1
5320      Major_mod1=1
5330      GOSUB Toggle
5340    CASE Active_col+1 TO Y_min_col-1  !application dependent columns
5350      IF (Num_choices(Col)>1) AND (Row<=Num_live_rows+1) THEN 
5360        Modified=1
5370        Major_mod1=1
5380        !find the choice_num of the current selection and decrement
5390        IF Row=1 THEN  !first row is "all"
5400          CALL Lib_match2(Box$(Col,2),Choices$(*),Col,Found,Choice_num)
5410        ELSE
5420          CALL Lib_match2(Box$(Col,Row),Choices$(*),Col,Found,Choice_num)
5430        END IF
5440        Choice_num=Choice_num-1
5450        IF Choice_num<1 THEN Choice_num=Num_choices(Col)
5460        IF Row=1 THEN 
5470          FOR R=2 TO Num_live_rows+1
5480            Box$(Col,R)=Choices$(Col,Choice_num)
5490          NEXT R
5500        ELSE
5510          Box$(Col,Row)=Choices$(Col,Choice_num)
5520        END IF
5530      ELSE
5540        BEEP 651,.03
5550      END IF
5560    CASE ELSE                !other column
5570      BEEP 651,.03
5580    END SELECT
5590    RETURN 
5600 Next_choice:   !-------------------------------------------------
5610    SELECT Col
5620    CASE Active_col
5630      Modified=1
5640      Major_mod1=1
5650      GOSUB Toggle
5660    CASE Active_col+1 TO Y_min_col-1  !application dependent columns
5670      IF (Num_choices(Col)>1) AND (Row<=Num_live_rows+1) THEN 
5680        Modified=1
5690        Major_mod1=1
5700        !find the choice_num of the current selection and increment
5710        IF Row=1 THEN  !first row is "all"
5720          CALL Lib_match2(Box$(Col,2),Choices$(*),Col,Found,Choice_num)
5730        ELSE
5740          CALL Lib_match2(Box$(Col,Row),Choices$(*),Col,Found,Choice_num)
5750        END IF
5760        Choice_num=Choice_num+1
5770        IF Choice_num>Num_choices(Col) THEN Choice_num=1
5780        IF Row=1 THEN     !ALL rows
5790          FOR R=2 TO Num_live_rows+1
5800            Box$(Col,R)=Choices$(Col,Choice_num)
5810          NEXT R
5820        ELSE
5830          Box$(Col,Row)=Choices$(Col,Choice_num)
5840        END IF
5850      ELSE
5860        BEEP 651,.03
5870      END IF
5880    CASE ELSE                !other column
5890      BEEP 651,.03
5900    END SELECT
5910    RETURN 
5920 Toggle:       !--------------------------------------------------
5930    IF Row=1 THEN         !ALL rows
5940      IF Box$(Col,2)="*" THEN 
5950        FOR R=2 TO Max_row
5960          Box$(Col,R)=""
5970        NEXT R
5980        FOR R=Num_live_rows+2 TO Max_row
5990          Box$(Active_col+1,R)="Recall trace "&VAL$(R-Num_live_rows-1)
6000        NEXT R
6010      ELSE
6020        FOR R=2 TO Num_live_rows+1
6030          Box$(Col,R)="*"
6040        NEXT R
6050      END IF
6060    ELSE
6070      IF Box$(Col,Row)="*" THEN 
6080        IF Row<=Num_live_rows+1 THEN     !live traces
6090          Box$(Col,Row)=""
6100        ELSE
6110          GOSUB Cancel_recall
6120        END IF
6130      ELSE
6140        IF Row<=Num_live_rows+1 THEN     !live traces
6150          Box$(Col,Row)="*"
6160        ELSE
6170          GOSUB Recall_trace
6180        END IF
6190      END IF
6200    END IF
6210    RETURN 
6220 Recall_trace:  !-----------------------------------------------------
6230    CALL Disp_recall_tr(Row-Num_live_rows-1,Box$(Active_col+1,Row),Ok)
6240    IF Ok THEN 
6250      Box$(Active_col,Row)="*"
6260    ELSE
6270      GOSUB Cancel_recall
6280    END IF
6290    RETURN 
6300 Cancel_recall: !-----------------------------------------------------
6310    Box$(Active_col,Row)=""
6320    Box$(Active_col+1,Row)="Recall trace "&VAL$(Row-Num_live_rows-1)
6330    RETURN 
6340 Label_keys:    !------------------------------------------------------
6350 ! Overwrite unused softkeys
6360    ON KEY 5 LABEL FNUser_keylabel$("Reset") CALL User_key5isr
6370    IF FNPlot_have_color THEN 
6380      IF FNPlot_use_color THEN 
6390        ON KEY 6 LABEL FNUser_keylabel$("Color *") CALL User_key6isr
6400      ELSE
6410        ON KEY 6 LABEL FNUser_keylabel$("Color") CALL User_key6isr
6420      END IF
6430    ELSE
6440      ON KEY 6 LABEL "" CALL User_key6isr
6450    END IF
6460    ON KEY 7 LABEL FNUser_keylabel$("Previous") CALL User_key7isr
6470    ON KEY 8 LABEL FNUser_keylabel$("Next") CALL User_key8isr
6480    RETURN 
6490  SUBEND
6500  ! PAGE -> 
6510  !************************************************************************
6520 Disp_plot_set:SUB Disp_plot_set(Plot_to_buf(*),X_units$(*),Y_units$(*),Start_x(*),Per_bin_x(*),Start_bin(*),Num_bins(*),Y_def_max(*),Y_def_min(*))
6530    !Called to "program" the plot setup.  Must be called by the application
6540    !before Disp_plot_data is called, and whenever hardware or the display
6550    !changes.  This sub just "stores" the passed info in common for use
6560    !by other Disp_ subprograms such as Disp_plot_axis.
6570    !
6580!       Plot_to_buf(1:num_plots)  Array of buffer numbers, one for each
6590!                      plot.  Passed to Disp_plot_set so it knows
6600!                      which buffer to get each plot out of.
6610!       X_units$(1:num_plots)  like "Hz" or "Sec" for each plot.
6620!                      A "" means don't label the x axis. 10 chars max.
6630!       Y_units$(1:num_plots) like "V" or "dBVp".  A "" means don't
6640!                      label the Y axis. 10 chars max.
6650!       Start_x(1:num_plots) The X axis value of Data_buffer(plot_num,0)
6660!                      in real world units.
6670!       Per_bin_x(1:num_plots) The value of one x bin in real world
6680!                      units.
6690!       Start_bin(1:num_plots) Which element of Data_buffer to start plotting.
6700!       Num_bins(1:num_plots) Number of points to plot.
6710!       Y_def_max(1:num_plots), Y_def_min(*):  Y axis values to use when
6720!                      when "default" scaling is selected.
6730 !
6740    COM /Disp_num_plots/ Num_live_plots,Num_r_plots
6750    COM /Disp_y/ Y_max$(*),Y_min$(*)
6760    COM /Disp_buf/ Plot_to_buf_c(*),Start_bin_c(*),Num_bins_c(*)
6770    COM /Disp_units/ X_units_c$(*),Y_units_c$(*)
6780    COM /Disp_window/ X_min(*),X_max(*),Y_min(*),Y_max(*)
6790    COM /Disp_log/ Do_log_x(*),Do_log_y(*)
6800    COM /Disp_misc/ Y_units_len,Plots_done,R_plots_done
6810    !
6820    COM /Disp_recall1/ R_x_units$(*),R_y_units$(*),R_num_bins(*)
6830    COM /Disp_recall2/ R_x_min(*),R_x_max(*),R_y_def_min(*),R_y_def_max(*)
6840    COM /Disp_recall3/ R_do_log_x(*),R_do_log_y(*)
6850    COM /Disp_recall4/ Plot_to_r_buf(*)
6860    !
6870    !
6880    IF Num_live_plots>SIZE(Plot_to_buf,1) THEN CALL User_stop("Size of Plot_to_buf < num_plots in Disp_plot_data")
6890    Plots_done=0
6900    R_plots_done=0
6910    MAT Do_log_x= (0)
6920    MAT Do_log_y= (0)
6930    FOR P=1 TO Num_live_plots
6940      GOSUB Do_live_plot
6950    NEXT P
6960    IF Num_r_plots>0 THEN !do recalled plots with info in common
6970      FOR P=Num_live_plots+1 TO Num_live_plots+Num_r_plots
6980        GOSUB Do_recall_plot
6990      NEXT P
7000    END IF
7010    SUBEXIT
7020 Do_live_plot:     !-----------------------------------------------------
7030    Plot_to_buf_c(P)=Plot_to_buf(P)
7040    X_units_c$(P)=X_units$(P)
7050    Y_units_c$(P)=Y_units$(P)
7060    Start_bin(P)=MAX(0,Start_bin(P))
7070    Start_bin_c(P)=Start_bin(P)
7080    Num_bins_c(P)=Num_bins(P)
7090    IF Num_bins(P)<1 THEN CALL User_stop("ERROR: Num_bins <1 (Disp_plot_set)")
7100    IF Per_bin_x(P)<=0 THEN CALL User_stop("ERROR: Per_bin_x<=0 (Disp_plot_set)")
7110    X_min(P)=Start_x(P)+Start_bin(P)*Per_bin_x(P)
7120    X_max(P)=Start_x(P)+(Start_bin(P)+Num_bins(P)-1)*Per_bin_x(P)
7130    Y_min(P)=Y_def_min(P)
7140    IF Y_min$(P)<>"Default" THEN Y_min(P)=VAL(Y_min$(P))
7150    Y_max(P)=Y_def_max(P)
7160    IF Y_max$(P)<>"Default" THEN Y_max(P)=VAL(Y_max$(P))
7170    IF Y_max(P)<=Y_min(P) THEN Y_max(P)=Y_min(P)+1
7180    RETURN 
7190 Do_recall_plot:     !------------------------------------------------
7200    Do_log_x(P)=R_do_log_x(Plot_to_r_buf(P))
7210    Do_log_y(P)=R_do_log_y(Plot_to_r_buf(P))
7220    X_units_c$(P)=R_x_units$(Plot_to_r_buf(P))
7230    Y_units_c$(P)=R_y_units$(Plot_to_r_buf(P))
7240    Start_bin_c(P)=1
7250    Num_bins_c(P)=R_num_bins(Plot_to_r_buf(P))
7260    X_min(P)=R_x_min(Plot_to_r_buf(P))
7270    X_max(P)=R_x_max(Plot_to_r_buf(P))
7280    Y_min(P)=R_y_def_min(Plot_to_r_buf(P))
7290    IF Y_min$(P)<>"Default" THEN Y_min(P)=VAL(Y_min$(P))
7300    Y_max(P)=R_y_def_max(Plot_to_r_buf(P))
7310    IF Y_max$(P)<>"Default" THEN Y_max(P)=VAL(Y_max$(P))
7320    IF Y_max(P)<=Y_min(P) THEN Y_max(P)=Y_min(P)+1
7330    IF Do_log_y(P) AND (Y_max(P)<=0) THEN Y_max(P)=1    !aviod LOG(0)
7340    IF Do_log_y(P) AND (Y_min(P)<=0) THEN Y_min(P)=Y_max(P)/1000
7350    RETURN 
7360  SUBEND
7370  ! PAGE -> 
7380  !************************************************************************
7390 Disp_plot_axis:SUB Disp_plot_axis
7400   !This subprogram plots grids and labels the axis for all the plots.
7410    COM /Disp_titles/ Plot_titles$(*)
7420    COM /Disp_units/ X_units$(*),Y_units$(*)
7430    COM /Disp_window/ X_min(*),X_max(*),Y_min(*),Y_max(*)
7440    COM /Disp_log/ Do_log_x(*),Do_log_y(*)
7450    COM /Disp_num_plots/ Num_live_plots,Num_r_plots
7460    COM /Disp_misc/ Y_units_len,Plots_done,R_plots_done
7470    CSIZE FNPlot_good_csize
7480    Plots_done=0
7490    R_plots_done=0
7500    CALL User_clr_scr
7510    !first figure Y_units_len, how many characters of room to leave
7520    !at the left of the plot for the y axis labels.
7530    !One value is used for all plots for atheistics.
7540    Y_units_len=0
7550    Total_num_plots=Num_live_plots+Num_r_plots
7560    FOR P=1 TO Total_num_plots
7570      L=LEN(Y_units$(P))
7580      IF L<>0 THEN 
7590        L=MAX(5,L)          !4 for numbers +1 for prefix
7600      END IF
7610      Y_units_len=MAX(Y_units_len,L+1)    !+1 space
7620    NEXT P
7630    !
7640    !now draw axis, background  and grid for each plot
7650    FOR P=1 TO Total_num_plots
7660      IF FNUser_key_press THEN SUBEXIT
7670      CALL Plot_set_viewp(Total_num_plots,P,X_label_length,Y_units_len,0)
7680      CALL Plot_do_axes(Plot_titles$(P),X_units$(P),Y_units$(P),X_min(P),X_max(P),Y_min(P),Y_max(P),X_label_length)
7690      !now change viewport to 1 pixel inside axes
7700      CALL Plot_set_viewp(Total_num_plots,P,X_label_length,Y_units_len,1)
7710      CALL Plot_background
7720      IF FNPlot_x_pixel<1/130 THEN !if there is enough resolution
7730        CALL Plot_grid(X_min(P),X_max(P),Y_min(P),Y_max(P),Do_log_x(P),Do_log_y(P))
7740      END IF
7750    NEXT P
7760  SUBEND
7770  ! PAGE -> 
7780  !************************************************************************
7790 Disp_plot_data:SUB Disp_plot_data(Buf(*),Head(*))
7800   !This subprogram draws the data for the plot.
7810   !New trace data is passed in, Trace selection info and
7820   !plot scaling info should be left in COM from previous calls to
7830   !Disp_put_trace and Disp_plot_set.  Plot titles and axis labels
7840   !should be left on the screen by a previous call to Disp_plot_axis.
7850   !
7860   !For each plot, Plot_make_x and Plot_make_y are called to make
7870   !the Plot_array(*) which is passed to Plot_do_data.
7880    COM /Disp_num_plots/ Num_live_plots,Num_r_plots
7890    COM /Disp_buf/ Plot_to_buf(*),Start_bin(*),Num_bins(*)
7900    COM /Disp_window/ X_min(*),X_max(*),Y_min(*),Y_max(*)
7910    COM /Disp_log/ Do_log_x(*),Do_log_y(*)
7920    COM /Disp_misc/ Y_units_len,Plots_done,R_plots_done
7930    COM /Disp_recall/ Recall_buf(*),Recall_head(*)
7940    COM /Disp_recall4/ Plot_to_r_buf(*)
7950    COM /Disp_plot_array/ C_plot_array(*),C_p_size
7960    DIM Message$[100]
7970    CSIZE FNPlot_good_csize
7980    Plots_done=0
7990   !There are 2 possibilities for Plot_array(*):
8000   !   C_plot_array(*) is used if it is big enough, since Plot_make_x
8010   !               is smart enough to not re-compute x if not needed.
8020   !   A_plot_array(*) is used if C_plot_array is not big enough.
8030   !
8040    IF MAX(Num_bins(*))>C_p_size THEN  !need to allocate
8050      ALLOCATE A_plot_array(1:MAX(Num_bins(*)),1:2)  !matrix PLOT array
8060      Use_a=1
8070    ELSE                          !use array in common
8080      Use_a=0
8090    END IF
8100    Total_num_plots=Num_live_plots+Num_r_plots
8110    GOSUB Do_data
8120    IF (Num_r_plots>0) AND NOT R_plots_done THEN 
8130      GOSUB Do_recall_data
8140      R_plots_done=1
8150    END IF
8160    Plots_done=1
8170    SUBEXIT
8180 Do_data:  !-----------------------------------------------------------
8190    FOR P=1 TO Num_live_plots
8200      IF FNUser_key_press THEN 
8210        !leave early, unless its the marker key
8220        IF FNUser_check_key<>6 THEN SUBEXIT
8230      END IF
8240      IF Do_log_y(P) THEN !y axis is displayed logarithmically
8250        IF Head(Plot_to_buf(P),4)<>0 THEN 
8260          CALL User_error("Can not do double LOG of Y axis")
8270        END IF
8280      END IF
8290      IF Head(Plot_to_buf(P),2)=0 THEN 
8300        CALL User_stop("Data_header Scale factor is zero")
8310        Head(Plot_to_buf(P),2)=1
8320      END IF
8330      Stop_bin=Start_bin(P)+Num_bins(P)-1
8340      Stop_bin=MIN(Stop_bin,SIZE(Buf,2)-1)
8350      Overload=Head(Plot_to_buf(P),3)
8360      Average=Head(Plot_to_buf(P),6)
8370      Real_time=Head(Plot_to_buf(P),7)
8380      !
8390      Message$=""
8400      IF Real_time THEN Message$="RT "
8410      IF Average THEN Message$=Message$&"Avg "&VAL$(Average)
8420      !get plot_array ready before clearing old plot
8430      IF Use_a THEN 
8440        REDIM A_plot_array(Start_bin(P):Stop_bin,1:2)
8450        CALL Plot_make_y(Buf(*),Head(*),A_plot_array(*),Plot_to_buf(P),Start_bin(P),Stop_bin,Do_log_y(P),Offset,Scale_factor)
8460        CALL Plot_make_x(A_plot_array(*),Do_log_x(P),X_min(P),X_max(P))
8470      ELSE
8480        REDIM C_plot_array(Start_bin(P):Stop_bin,1:2)
8490        CALL Plot_make_y(Buf(*),Head(*),C_plot_array(*),Plot_to_buf(P),Start_bin(P),Stop_bin,Do_log_y(P),Offset,Scale_factor)
8500        CALL Plot_make_x(C_plot_array(*),Do_log_x(P),X_min(P),X_max(P))
8510      END IF
8520      !
8530      !clear old plot
8540      CALL Plot_set_viewp(Total_num_plots,P,0,Y_units_len,1)
8550      CALL Plot_background
8560      IF FNPlot_x_pixel<1/130 THEN !if there is enough resolution
8570        CALL Plot_grid(X_min(P),X_max(P),Y_min(P),Y_max(P),Do_log_x(P),Do_log_y(P))
8580      END IF
8590      !
8600      !plot new data
8610      IF Use_a THEN 
8620        CALL Plot_do_data(A_plot_array(*),Overload,Message$,Y_min(P),Y_max(P),Offset,Scale_factor,Do_log_y(P))
8630      ELSE
8640        CALL Plot_do_data(C_plot_array(*),Overload,Message$,Y_min(P),Y_max(P),Offset,Scale_factor,Do_log_y(P))
8650      END IF
8660    NEXT P
8670    RETURN 
8680 Do_recall_data:  !-----------------------------------------------------------
8690    FOR P=Num_live_plots+1 TO Num_live_plots+Num_r_plots
8700      IF FNUser_key_press THEN 
8710        !leave early, unless its the marker key
8720        IF FNUser_check_key<>6 THEN SUBEXIT
8730      END IF
8740      Stop_bin=Start_bin(P)+Num_bins(P)-1
8750      Overload=Recall_head(Plot_to_r_buf(P),3)
8760      !get plot_array ready before clearing old plot
8770      IF Use_a THEN 
8780        REDIM A_plot_array(Start_bin(P):Stop_bin,1:2)
8790        CALL Plot_make_y(Recall_buf(*),Recall_head(*),A_plot_array(*),Plot_to_r_buf(P),Start_bin(P),Stop_bin,Do_log_y(P),Offset,Scale_factor)
8800        CALL Plot_make_x(A_plot_array(*),Do_log_x(P),X_min(P),X_max(P))
8810      ELSE
8820        REDIM C_plot_array(Start_bin(P):Stop_bin,1:2)
8830        CALL Plot_make_y(Recall_buf(*),Recall_head(*),C_plot_array(*),Plot_to_r_buf(P),Start_bin(P),Stop_bin,Do_log_y(P),Offset,Scale_factor)
8840        CALL Plot_make_x(C_plot_array(*),Do_log_x(P),X_min(P),X_max(P))
8850      END IF
8860      !
8870      !clear old plot
8880      CALL Plot_set_viewp(Total_num_plots,P,0,Y_units_len,1)
8890      CALL Plot_background
8900      IF FNPlot_x_pixel<1/130 THEN !if there is enough resolution
8910        CALL Plot_grid(X_min(P),X_max(P),Y_min(P),Y_max(P),Do_log_x(P),Do_log_y(P))
8920      END IF
8930      !
8940      !plot new data
8950      IF Use_a THEN 
8960        CALL Plot_do_data(A_plot_array(*),Overload,"Recalled",Y_min(P),Y_max(P),Offset,Scale_factor,Do_log_y(P))
8970      ELSE
8980        CALL Plot_do_data(C_plot_array(*),Overload,"Recalled",Y_min(P),Y_max(P),Offset,Scale_factor,Do_log_y(P))
8990      END IF
9000    NEXT P
9010    RETURN 
9020  SUBEND
9030  ! PAGE -> 
9040  !************************************************************************
9050 Disp_do_mkr:SUB Disp_do_mkr(Buf(*),Head(*),Redraw)
9060    !This subprogram handles the marker.  It Does not return
9070    !until an unknown softkey is pressed.  It sets up softkeys to do
9080    !marker functions and store traces in disc files.
9090    COM /Disp_buf/ Plot_to_buf(*),Start_bin(*),Num_bins(*)
9100    COM /Disp_units/ X_units$(*),Y_units$(*)
9110    COM /Disp_window/ X_min(*),X_max(*),Y_min(*),Y_max(*)
9120    COM /Disp_log/ Do_log_x(*),Do_log_y(*)
9130    COM /Disp_misc/ Y_units_len,Plots_done,R_plots_done
9140    COM /Disp_recall/ Recall_buf(*),Recall_head(*)
9150    COM /Disp_recall4/ Plot_to_r_buf(*)
9160    COM /Disp_mkr/ Mkr_plot
9170    COM /Disp_num_plots/ Num_live_plots,Num_r_plots
9180    Total_num_plots=Num_live_plots+Num_r_plots
9190    IF Redraw THEN CALL Disp_plot_axis
9200    IF Redraw OR NOT Plots_done THEN CALL Disp_plot_data(Buf(*),Head(*))
9210    ALLOCATE Plot_array(1:MAX(Num_bins(*),SIZE(Recall_buf,2)),1:2)  !matrix PLOT array
9220    IF FNUser_key_press THEN SUBEXIT
9230    ON KEY 1 LABEL FNUser_keylabel$("Marker to X") CALL User_key1isr
9240    ON KEY 2 LABEL FNUser_keylabel$("Marker to Min") CALL User_key2isr
9250    ON KEY 3 LABEL FNUser_keylabel$("Marker to Max") CALL User_key3isr
9260    ON KEY 4 LABEL FNUser_keylabel$("Store Trace") CALL User_key4isr
9270    ! 5 is not used
9280    ! 6 will be "MAIN"
9290    ON KEY 7 LABEL FNUser_keylabel$("Previous Trace") CALL User_key7isr
9300    ON KEY 8 LABEL FNUser_keylabel$("Next Trace") CALL User_key8isr
9310    Done=0
9320    GOSUB New_mkr_plot
9330    REPEAT
9340      CALL Plot_set_viewp(Total_num_plots,P,0,Y_units_len,1)
9350      CALL Plot_do_mkr(Plot_array(*),X_units$(P),Y_units$(P),X_min(P),X_max(P),Y_min(P),Y_max(P),Offset,Scale_factor,Do_log_y(P))
9360      SELECT FNUser_check_key
9370      CASE 1     !move marker
9380        Dummy=FNUser_get_key      !to clear the key
9390        Plot_move_mkr(Plot_array(*),X_units$(P),X_min(P),X_max(P),"X")
9400      CASE 2   !move marker to min
9410        Dummy=FNUser_get_key      !to clear the key
9420        Plot_move_mkr(Plot_array(*),X_units$(P),X_min(P),X_max(P),"MIN")
9430      CASE 3     !move marker to max
9440        Dummy=FNUser_get_key      !to clear the key
9450        Plot_move_mkr(Plot_array(*),X_units$(P),X_min(P),X_max(P),"MAX")
9460      CASE 4     !store
9470        Dummy=FNUser_get_key      !to clear the key
9480        CALL Disp_store_tr(Plot_array(*),P,Overload,Offset,Scale_factor)
9490      CASE 7    !prev
9500        Dummy=FNUser_get_key      !to clear the key
9510        Mkr_plot=Mkr_plot-1
9520        IF Mkr_plot=0 THEN Mkr_plot=Total_num_plots
9530        GOSUB New_mkr_plot
9540      CASE 8    !next
9550        Dummy=FNUser_get_key
9560        Mkr_plot=Mkr_plot+1
9570        IF Mkr_plot>Total_num_plots THEN Mkr_plot=1
9580        GOSUB New_mkr_plot
9590      CASE ELSE
9600        Done=1
9610      END SELECT
9620    UNTIL Done
9630    SUBEXIT
9640 New_mkr_plot:    !----------------------------------------------------
9650    Mkr_plot=MAX(1,MIN(Total_num_plots,Mkr_plot))
9660    P=Mkr_plot      !shorter variable name
9670    Stop_bin=Start_bin(P)+Num_bins(P)-1
9680    IF P>Num_live_plots THEN    !recalled trace, get from Recall_buf(*)
9690      REDIM Plot_array(Start_bin(P):Stop_bin,1:2)
9700      CALL Plot_make_y(Recall_buf(*),Recall_head(*),Plot_array(*),Plot_to_r_buf(P),Start_bin(P),Stop_bin,Do_log_y(P),Offset,Scale_factor)
9710      CALL Plot_make_x(Plot_array(*),Do_log_x(P),X_min(P),X_max(P))
9720      Overload=Recall_head(Plot_to_r_buf(P),3)
9730    ELSE                    !not recalled, get Plot_array from Buf(*)
9740      Stop_bin=MIN(Stop_bin,SIZE(Buf,2)-1)
9750      REDIM Plot_array(Start_bin(P):Stop_bin,1:2)
9760      CALL Plot_make_y(Buf(*),Head(*),Plot_array(*),Plot_to_buf(P),Start_bin(P),Stop_bin,Do_log_y(P),Offset,Scale_factor)
9770      CALL Plot_make_x(Plot_array(*),Do_log_x(P),X_min(P),X_max(P))
9780      Overload=Head(Plot_to_buf(P),3)
9790    END IF
9800    RETURN 
9810  SUBEND
9820  ! PAGE -> 
9830  !************************************************************************
9840 Disp_choice:DEF FNDisp_choice(Plot_num,Category_num)
9850  !This function returns the current selection of an application
9860  !dependent column of the display spread sheet.  It returns an index
9870  !into the array Choices$(*), given the plot number and category number.
9880    COM /Disp_choice/ Plot_choice(*)
9890    RETURN Plot_choice(Plot_num,Category_num)
9900  FNEND
9910  !************************************************************************
9920 Disp_num_plots:DEF FNDisp_num_plots
9930    !This function returns the number of plots, not counting recalled traces.
9940    COM /Disp_num_plots/ Num_live_plots,Num_r_plots
9950    RETURN Num_live_plots
9960  FNEND
9970  ! PAGE -> 
9980  !************************************************************************
9990 Disp_update_com:SUB Disp_update_com
10000 !This subprogram is called before exiting Disp_spread to translate
10010 !from spreadsheet form to plot form.
10020   COM /Disp_spread1/ Box$(*),Row,Col,Start_row
10030   COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
10040   COM /Disp_spread4/ Choices$(*),Num_choices(*)
10050   COM /Disp_choice/ Plot_choice(*)
10060   COM /Disp_recall4/ Plot_to_r_buf(1:16)
10070   ALLOCATE Plot_titles$(1:16)[45],Y_max$(1:16)[20],Y_min$(1:16)[20]
10080   DIM Title$[255],Temp$[40]
10090   !copy Box$ info into  arrays for passing to Disp_put_traces
10100   Max_row=SIZE(Box$,2)
10110   Num_live_plots=0
10120   Num_r_plots=0
10130   FOR R=2 TO Num_live_rows+1        !for each live row, check for active trace
10140     IF Box$(Active_col,R)="*" THEN 
10150       GOSUB Do_the_row
10160     END IF
10170   NEXT R
10180   IF Num_live_plots<1 THEN 
10190     R=2
10200     Box$(Active_col,R)="*"    !make first one active
10210     GOSUB Do_the_row
10220     CALL User_error("You must have at least one active trace")
10230   END IF
10240   FOR R=Num_live_rows+2 TO Max_row        !for each recall row, check for active trace
10250     IF Box$(Active_col,R)="*" THEN 
10260       GOSUB Do_the_row
10270     END IF
10280   NEXT R
10290   CALL Disp_put_traces(Num_live_plots,Num_r_plots,Y_max$(*),Y_min$(*))
10300   CALL Disp_put_titles(Plot_titles$(*))
10310   SUBEXIT
10320 Do_the_row: !-------------------------------------------------------
10330   !processes row R  of the spread sheet data
10340   IF Num_live_plots+Num_r_plots<16 THEN 
10350     IF R<=Num_live_rows+1 THEN 
10360       Num_live_plots=Num_live_plots+1
10370     ELSE        !recalled plots
10380       Num_r_plots=Num_r_plots+1
10390     END IF
10400     Plot_num=Num_live_plots+Num_r_plots
10410     !
10420     !built title out of application dependent cols
10430     Title$=""
10440     FOR C=Active_col+1 TO Y_min_col-1
10450       Title$=Title$&Box$(C,R)&" "
10460     NEXT C
10470     Title$=TRIM$(Title$)
10480     IF LEN(Title$)<45 THEN 
10490       Plot_titles$(Plot_num)=Title$
10500     ELSE
10510       Plot_titles$(Plot_num)=Title$[1,45]
10520     END IF
10530     !
10540     !check for swapped min/max
10550     IF Box$(Y_min_col,R)<>"Default" AND Box$(Y_max_col,R)<>"Default" THEN 
10560       IF VAL(Box$(Y_min_col,R))>VAL(Box$(Y_max_col,R)) THEN     !min>max ?
10570         Temp$=Box$(Y_min_col,R)
10580         Box$(Y_min_col,R)=Box$(Y_max_col,R)
10590         Box$(Y_max_col,R)=Temp$
10600       END IF
10610     END IF
10620     Y_min$(Plot_num)=Box$(Y_min_col,R)
10630     Y_max$(Plot_num)=Box$(Y_max_col,R)
10640     !
10650     IF R<=Num_live_rows+1 THEN              !live trace
10660       !encode application dependent stuff
10670       FOR C=Active_col+1 TO Y_min_col-1!for each appl dependent col
10680         CALL Lib_match2(Box$(C,R),Choices$(*),C,Found,Choice_num)
10690         IF Found THEN 
10700           Plot_choice(Plot_num,C-Active_col)=Choice_num
10710         ELSE
10720           CALL User_stop("match failed")
10730         END IF
10740       NEXT C
10750     ELSE                                    !recalled trace
10760       Plot_to_r_buf(Plot_num)=R-Num_live_rows-1
10770     END IF
10780   END IF     !plots<=16
10790   RETURN 
10800 SUBEND
10810 ! PAGE -> 
10820 !************************************************************************
10830 Disp_reset:SUB Disp_reset
10840 !This subprogram resets the display spread sheet to its initial state.
10850 !The initial state defines up to 16 plots unique plots using all
10860 !combinations of Choices$() for each application dependent column.
10870 !Y axis scaling is set to "Default", and several plots are set active.
10880 !
10890   COM /Disp_spread1/ Box$(*),Row,Col,Start_row
10900   COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
10910   COM /Disp_spread4/ Choices$(*),Num_choices(*)
10920   INTEGER A(0:5)
10930   GESCAPE CRT,3;A(*)   !get CRT pixel size in A(*)
10940   IF A(2)>1000 THEN    !if CRT is high resolution then
10950     Max_active=9       !display up to 9 traces as default
10960   ELSE
10970     Max_active=4
10980   END IF
10990 !
11000   MAT Box$= ("")
11010   Max_row=SIZE(Box$,2)
11020   !
11030   !set up "All" row
11040   Box$(1,1)="All"
11050   ALLOCATE Current_choice(3:3+Num_categories)
11060   !Current_choice has an element for each column (category) to be varied.
11070   !The values are the choice numbers and are incremented in a ripple
11080   !counter like fashion.
11090   MAT Current_choice= (1)  !first row is first choice for all categories.
11100   FOR R=2 TO Num_live_rows+1
11110     Box$(1,R)=VAL$(R-1)
11120     IF (R-1)<=Max_active THEN Box$(Active_col,R)="*"
11130     FOR C=3 TO 2+Num_categories
11140       Box$(C,R)=Choices$(C,Current_choice(C))
11150     NEXT C
11160     Box$(Y_min_col,R)="Default"
11170     Box$(Y_max_col,R)="Default"
11180     !increment current_choice array
11190     Current_choice(3)=Current_choice(3)+1  !increment choice in left most col
11200     FOR C=3 TO 2+Num_categories            !check each col for wrap
11210       IF Current_choice(C)>Num_choices(C) THEN !need to "carry"
11220         Current_choice(C)=1
11230         Current_choice(C+1)=Current_choice(C+1)+1
11240       END IF
11250     NEXT C
11260   NEXT R
11270   FOR R=Num_live_rows+2 TO Max_row
11280     Box$(1,R)="R "&VAL$(R-Num_live_rows-1)
11290     Box$(Active_col,R)=""
11300     Box$(Y_min_col,R)="Default"
11310     Box$(Y_max_col,R)="Default"
11320     Box$(Active_col+1,R)="Recall trace "&VAL$(R-Num_live_rows-1)
11330   NEXT R
11340 SUBEND
11350 ! PAGE -> 
11360 !************************************************************************
11370 Disp_save:SUB Disp_save(@File,Ok)
11380 !This subprogram saves the state of the display spreadsheet
11390 !into file @File.
11400 !
11410   COM /Disp_spread1/ Box$(*),Row,Col,Start_row
11420   !
11430   !
11440   File_format_rev=2621
11450   OUTPUT @File;File_format_rev
11460   !
11470   CALL File_save_s(@File,Box$(*))
11480   Ok=1
11490   !
11500 SUBEND
11510 !************************************************************************
11520 Disp_load:SUB Disp_load(@File,Ok)
11530 !This subprogram loads the state of the display spreadsheet
11540 !from file @File.  Disp_put_traces must be called by the application
11550 !to update other items.
11560 !
11570   COM /Disp_spread1/ Box$(*),Row,Col,Start_row
11580   COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
11590   !
11600   !
11610   ENTER @File;File_format_rev
11620   SELECT File_format_rev
11630   CASE 2621
11640     CALL File_load_s(@File,Box$(*))
11650   !
11660   CASE ELSE  !unknown rev
11670     CALL User_error("ERROR Incompatible display file format in Disp_load.")
11680     Ok=0
11690     SUBEXIT
11700   END SELECT
11710   !
11720   !Turn off recall traces
11730   FOR R=2 TO SIZE(Box$,2)
11740     IF POS(Box$(1,R),"R") THEN 
11750       Box$(Active_col,R)=""
11760       Box$(Active_col+1,R)="Recall trace "&VAL$(R-Num_live_rows-1)
11770     END IF
11780   NEXT R
11790   !
11800   CALL Disp_update_com
11810   Ok=1
11820   !
11830 SUBEND
11840 ! PAGE -> 
11850 !************************************************************************
11860 Disp_store_tr:SUB Disp_store_tr(Plot_array(*),P,Overload,Offset,Scale_factor)
11870 !This subprogram outputs the trace to an ASCII file.  The format is
11880 !HP's implementation of the Neutral File format.
11890 !---------------------------------------------------------------------
11900   COM /Disp_titles/ Plot_titles$(*)
11910   COM /Disp_units/ X_units$(*),Y_units$(*)
11920   COM /Disp_window/ X_min(*),X_max(*),Y_min(*),Y_max(*)
11930   COM /Disp_log/ Do_log_x(*),Do_log_y(*)
11940   DIM File_name$[160]
11950   File_size=(12*40+SIZE(Plot_array,1)*25.0)/256
11960   LINPUT "Name of file for trace store ?",File_name$
11970   IF TRIM$(File_name$)="" THEN SUBEXIT
11980   ON ERROR GOTO Create_failed
11990   CREATE ASCII File_name$,File_size
12000   OFF ERROR 
12010   GOTO Created
12020 Create_failed:OFF ERROR 
12030   IF ERRN=54 THEN !duplicate file name
12040     IF NOT FNUser_yes("File already exists. OK to overwrite ? (Y or N)",1) THEN 
12050       CALL User_error("Trace Store Aborted.")
12060       SUBEXIT
12070     END IF
12080   ELSE
12090     CALL User_error("Store failed: "&ERRM$)
12100     SUBEXIT
12110   END IF
12120   ON ERROR GOTO Store_failed
12130   PURGE File_name$
12140   CREATE ASCII File_name$,File_size
12150 Created:!
12160   ON ERROR GOTO Store_failed
12170   ASSIGN @File TO File_name$
12180   GOSUB Write_heading
12190   GOSUB Write_data
12200   DISP "Store done"
12210   WAIT 3
12220   SUBEXIT
12230 Write_heading:  !-----------------------------------------------
12240   DISP "Storing ";Plot_titles$(P);" in file ";File_name$;" ."
12250   OUTPUT @File;"SPAMHDR("
12260   OUTPUT @File;"  XUNI:"&FNDisp_zap$(X_units$(P))&","
12270   OUTPUT @File;"  YUNI:"&FNDisp_zap$(Y_units$(P))&","
12280   OUTPUT @File;"  XMIN:"&VAL$(X_min(P))&","
12290   OUTPUT @File;"  XMAX:"&VAL$(X_max(P))&","
12300   OUTPUT @File;"  XLOG:"&VAL$(Do_log_x(P))&","
12310   OUTPUT @File;"  YLOG:"&VAL$(Do_log_y(P))&","
12320   OUTPUT @File;"  YDMI:"&VAL$(Y_min(P))&","
12330   OUTPUT @File;"  YDMA:"&VAL$(Y_max(P))&","
12340   OUTPUT @File;");"
12350   RETURN 
12360 Write_data:     !-----------------------------------------------
12370   DISP "Storing ";Plot_titles$(P);" in file ";File_name$;" .."
12380   INTEGER I,N
12390   N=SIZE(Plot_array,1)
12400   ALLOCATE Y(1:N),Y$(1:N)[21],Mask(1:2)
12410   Mask(1)=0  !ignore X of x,y point
12420   Mask(2)=1  !use Y
12430   MAT Y= Plot_array*Mask
12440   MAT Y= Y-(Offset)
12450   MAT Y= Y/(Scale_factor)
12460   !now do format to string array to avoid SRM limitations with USING.
12470   IF Do_log_y(P) THEN !need to un-log
12480     FOR I=1 TO N-1
12490       OUTPUT Y$(I) USING "#,MD.12DESZZZ,A";10^(Y(I)),","
12500     NEXT I
12510   ELSE
12520     FOR I=1 TO N-1
12530       OUTPUT Y$(I) USING "#,MD.12DESZZZ,A";Y(I),","
12540     NEXT I
12550   END IF
12560   OUTPUT Y$(N) USING "#,MD.12DESZZZ,A";Y(N)," "
12570   DISP "Storing ";Plot_titles$(P);" in file ";File_name$;" ..."
12580   OUTPUT @File;"DATAHDR("
12590   OUTPUT @File;"  LBL:"&FNDisp_zap$(Plot_titles$(P))&","
12600   OUTPUT @File;"  DATE:"&DATE$(TIMEDATE)&","
12610   OUTPUT @File;"  OVLD:"&VAL$(Overload)&","
12620   OUTPUT @File;"  DATA#ASCI,20,"&VAL$(SIZE(Plot_array,1))&":"
12630   OUTPUT @File;Y$(*)
12640   OUTPUT @File;");"
12650   RETURN 
12660 Store_failed:   !-------------------------------------------------
12670   CALL User_error("Store failed: "&ERRM$)
12680   WAIT 1
12690 SUBEND
12700 ! PAGE -> 
12710 !************************************************************************
12720 Disp_zap:DEF FNDisp_zap$(S$)
12730  !This function changes illegal characters to spaces.
12740   DIM R$[256]
12750   INTEGER I
12760   R$=""
12770   IF LEN(S$)>0 THEN 
12780     FOR I=1 TO LEN(S$)
12790       SELECT NUM(S$[I;1])
12800       CASE <32,>125,35,40,41,44,58,59!   < ,>},#,(,),,,:,;
12810         R$=R$&" "
12820       CASE ELSE                     !ok
12830         R$=R$&S$[I;1]
12840       END SELECT
12850     NEXT I
12860   END IF
12870   RETURN R$
12880 FNEND
12890 ! PAGE -> 
12900 !************************************************************************
12910 Disp_recall_tr:SUB Disp_recall_tr(R_buf_num,R_title$,Ok)
12920 !This subprogram reads a trace from a file.  The format is
12930 !HP's implementation of the Neutral File format.  The trace data is
12940 !stored in a buffer of the Recall_buf(*) array.
12950 !---------------------------------------------------------------------
12960   COM /Disp_recall/ Recall_buf(*),Recall_head(*)
12970   COM /Disp_recall1/ R_x_units$(*),R_y_units$(*),R_num_bins(*)
12980   COM /Disp_recall2/ R_x_min(*),R_x_max(*),R_y_def_min(*),R_y_def_max(*)
12990   COM /Disp_recall3/ R_do_log_x(*),R_do_log_y(*)
13000   !
13010   DIM File_name$[160],Line$[256]
13020   Ok=1
13030   Got_data=0
13040   ON ERROR GOTO Recall_failed
13050   LINPUT "Name of file for trace recall ?",File_name$
13060   IF TRIM$(File_name$)="" THEN 
13070     Ok=0
13080     SUBEXIT
13090   END IF
13100   ASSIGN @File TO File_name$
13110   GOSUB Set_defaults
13120   ON END @File GOTO Eof
13130   GOSUB Read_file
13140 Eof:DISP 
13150   IF NOT Got_data THEN Ok=0
13160   SUBEXIT
13170 Set_defaults:  !-----------------------------------------------
13180   R_x_units$(R_buf_num)=""
13190   R_y_units$(R_buf_num)=" "
13200   R_x_min(R_buf_num)=0
13210   R_x_max(R_buf_num)=1
13220   R_y_def_min(R_buf_num)=-1
13230   R_y_def_max(R_buf_num)=1
13240   R_do_log_x(R_buf_num)=0
13250   R_do_log_y(R_buf_num)=0
13260   R_num_bins(R_buf_num)=0
13270   R_title$="Recall trace "&VAL$(R_buf_num)
13280   Recall_head(R_buf_num,1)=0       !offset
13290   Recall_head(R_buf_num,2)=1       !scale factor
13300   Recall_head(R_buf_num,3)=0       !overload
13310   RETURN 
13320 Read_file:     !-----------------------------------------------
13330   DISP "Recalling from file ";File_name$;" ."
13340   WHILE Ok
13350     ENTER @File;Line$
13360     Line$=TRIM$(Line$)
13370     IF LEN(Line$)>5 THEN 
13380       IF Line$[LEN(Line$)]="," THEN Line$=Line$[1,LEN(Line$)-1]!delete ,
13390       SELECT UPC$(Line$[1,4])
13400       CASE "XUNI"
13410         R_x_units$(R_buf_num)=Line$[6]
13420       CASE "YUNI"
13430         R_y_units$(R_buf_num)=Line$[6]
13440       CASE "XMIN"
13450         R_x_min(R_buf_num)=VAL(Line$[6])
13460       CASE "XMAX"
13470         R_x_max(R_buf_num)=VAL(Line$[6])
13480       CASE "XLOG"
13490         R_do_log_x(R_buf_num)=VAL(Line$[6])
13500       CASE "YLOG"
13510         R_do_log_y(R_buf_num)=VAL(Line$[6])
13520       CASE "YDMI"
13530         R_y_def_min(R_buf_num)=VAL(Line$[6])
13540       CASE "YDMA"
13550         R_y_def_max(R_buf_num)=VAL(Line$[6])
13560       CASE "LBL:"
13570         R_title$=Line$[5]
13580       CASE "OVLD"
13590         Recall_head(R_buf_num,3)=VAL(Line$[6])
13600       CASE "DATA"
13610         IF POS(Line$,"DATA#ASCI") THEN GOSUB Read_data
13620       END SELECT
13630     END IF
13640   END WHILE
13650   RETURN 
13660 Read_data:     !-----------------------------------------------
13670   !comes here when Line$ is "DATA#ASCI,<bytes per items>,<num items>:"
13680   INTEGER I,N
13690   Line$=Line$[11]  !delete "DATA#ASCI,"
13700   ENTER Line$;Dummy,N
13710   R_num_bins(R_buf_num)=N
13720   IF N>SIZE(Recall_buf,2) THEN 
13730     CALL User_error("Recall failed:  Recall_buf(*) array is too small.")
13740     !size of array is defined in SUB Disp_disp
13750     Ok=0
13760   ELSE
13770     ALLOCATE Y(1:N)
13780     DISP "Recalling from file ";File_name$;" .."
13790     ENTER @File;Y(*)
13800     DISP "Recalling from file ";File_name$;" ..."
13810     FOR I=1 TO N
13820       Recall_buf(R_buf_num,I)=Y(I)
13830     NEXT I
13840     Got_data=1
13850   END IF
13860   RETURN 
13870 Recall_failed:   !-------------------------------------------------
13880   Ok=0
13890   CALL User_error("Recall failed: "&ERRM$)
13900   WAIT 1
13910 SUBEND
13920 ! PAGE -> 
13930 !************************************************************************
13940 Disp_put_traces:SUB Disp_put_traces(Num_live_plots,Num_r_plots,Y_max$(*),Y_min$(*))
13950   !This subprogram is called from Disp_spread or a non-interactive program to
13960   !define the plots.
13970   COM /Disp_y/ Y_max_c$(*),Y_min_c$(*)
13980   COM /Disp_num_plots/ Num_live_plotsc,Num_r_plots_c
13990   COM /Disp_misc/ Y_units_len,Plots_done,R_plots_done
14000   Num_live_plotsc=Num_live_plots
14010   Num_r_plots_c=Num_r_plots
14020   MAT Y_max_c$= Y_max$
14030   MAT Y_min_c$= Y_min$
14040 SUBEND
14050 ! PAGE -> 
14060 !************************************************************************
14070 Disp_put_titles:SUB Disp_put_titles(Plot_titles$(*))
14080   !This subprogram is called from Disp_spread or a non-interactive program to
14090   !define the plot titles.
14100   COM /Disp_titles/ Plot_titles_c$(*)
14110   FOR I=1 TO SIZE(Plot_titles$,1)
14111     IF LEN(Plot_titles$(I))>45 THEN 
14112       Plot_titles_c$(I)=Plot_titles$(I)[1,45]
14113     ELSE
14120       Plot_titles_c$(I)=Plot_titles$(I)
14121     END IF
14130   NEXT I
14140 SUBEND
14150 ! PAGE -> 
14160 !************************************************************************
14170 Disp_log_set:SUB Disp_log_set(Do_log_x(*),OPTIONAL Do_log_y(*))
14180   !This subprogram may be called to change plot axis to logarithmic.
14190   !It must be called
14200   !after Disp_plot_set since Disp_plot_set resets
14210   !all plots to linear.
14220   !Setting Do_log_y produces the same trace shape as setting
14230   !Data_header(*,4)=1.0  However, Do_log_y produces a log grid and
14240   !the marker is not logged.
14250!       Do_log_x(1:num_plots) Array of flags, one for each plot.
14260!                      0= linear X axis,  non-zero = log X axis.
14270!       Do_log_y(1:num_plots) Array of flags, one for each plot.
14280   !
14290   COM /Disp_num_plots/ Num_live_plots,Num_r_plots
14300   COM /Disp_buf/ Plot_to_buf(*),Start_bin(*),Num_bins(*)
14310   COM /Disp_window/ X_min(*),X_max(*),Y_min(*),Y_max(*)
14320   COM /Disp_log/ Do_log_x_c(*),Do_log_y_c(*)
14330   !
14340   FOR P=1 TO Num_live_plots
14350     Do_log_x_c(P)=0
14360     IF Do_log_x(P) THEN 
14370       IF X_max(P)>0 THEN 
14380         IF X_min(P)>0 THEN   !all ok as is
14390           Do_log_x_c(P)=1
14400         ELSE                 !need to change start_bin to avoid negative x
14410           Per_bin_x=(X_max(P)-X_min(P))/(Num_bins(P)-1)
14420           Bins=INT(-X_min(P)/Per_bin_x+1)
14430           Start_bin(P)=Start_bin(P)+Bins
14440           Num_bins(P)=Num_bins(P)-Bins
14450           X_min(P)=X_min(P)+Per_bin_x*Bins
14460           Do_log_x_c(P)=1
14470         END IF
14480       ELSE  !x_max<0
14490         CALL User_error("NOTE: Can't do LOG of negative X-axis")
14500       END IF
14510     END IF
14520   NEXT P
14530   IF NPAR>1 THEN 
14540     FOR P=1 TO Num_live_plots
14550       Do_log_y_c(P)=0
14560       IF Do_log_y(P) THEN 
14570         IF Y_max(P)>0 THEN 
14580           IF Y_min(P)>0 THEN !all ok as is
14590             Do_log_y_c(P)=1
14600           ELSE               !need to change Y_min
14610             Y_min(P)=Y_max(P)/1000
14620             Do_log_y_c(P)=1
14630           END IF
14640         ELSE!x_max<0
14650           CALL User_error("NOTE: Can't do LOG of negative Y-axis")
14660         END IF
14670       END IF
14680     NEXT P
14690   END IF
14700 SUBEND
14710 ! PAGE -> 
14720 !************************************************************************
14730 Disp_reset_y:SUB Disp_reset_y
14740  !This subprogram may be called to reset the Y axis scaling of the
14750  !display spread sheet to "Default" for all the live rows.
14760   COM /Disp_spread1/ Box$(*),Row,Col,Start_row
14770   COM /Disp_spread3/ Active_col,Y_max_col,Y_min_col,Num_categories,Num_live_rows,Num_recall_rows
14780   FOR R=2 TO Num_live_rows+1
14790     Box$(Y_max_col,R)="Default"
14800     Box$(Y_min_col,R)="Default"
14810   NEXT R
14820   CALL Disp_update_com
14830 SUBEND