/* GraphPrint.rexx
 * Render a TeX diagram of Fiasco data
 * Requires rexxsupport.library and
 * rexxmathlib.library by Willy Langeveld
 * Created documents require LaTeX, epic, eepic and specialhost running
 * Copyright © 1996 Nils Bandener
 * $VER: GraphPrint.rexx 4.18 (24.9.96)
 */

/* To Do:
 *
 * Support for several graphs in one diagram
 * Configure use of TeX program (bigtex/virtex)
 *
 */

Options Results
Address FIASCO

Signal on Syntax
Signal on Halt
Signal on Break_C
Signal on Failure

F_LockGUI

/*
 *  Get fields for graphic
 */

F_RequestField '"Please select a field*nfor the x axis"'
if rc ~= 0 then call bailout
xname = result
xlabel = result     /* xlabel is used in the graphic */

F_RequestField '"Please select a field*nfor the y axis"'
if rc ~= 0 then call bailout
yname = result
ylabel = result     /* ylable is used in the graphic */

F_RequestChoice '"Do you want to save the result in a TeX file*nor compile it temporarily for viewing or printing?" "Save to file|View/Print"'
desttype = result

if desttype = 1 then do
    F_RequestFile '"Ram:FiascoOutput.tex" Pattern "#?.tex" Title "Select a TeX file" Savemode'
    if rc ~= 0 then call bailout
    texfile = result

    F_RequestChoice '"Do you want a complete file*nor a file without headers usable for \input?" "Complete|Without headers"'
    completefile = result

end
else do
    texfile = "t:FiascoOutput.tex"
    completefile = 1
end

/*
 * Define a symbol for value positions
 */

cross = "\makebox(0,0){$\otimes$}"

/*
 * Open libraries
 */

if ~show(libraries, "rexxsupport.library") then do

    if ~addlib("rexxsupport.library", 0, -30, 0) then do

        F_RequestChoice '"Could not open*nrexxsupport.library"' '"Cancel"'

        call bailout

    end
end

if ~show(libraries, "rexxmathlib.library") then do

    if ~addlib("rexxmathlib.library", 0, -30, 0) then do

        F_RequestChoice '"Could not open*nrexxmathlib.library"' '"Cancel"'

        call bailout

    end
end

F_CountRecs
num = result

/*
 *  Search for extrema
 */

F_SetStatus '"extrema..."'

F_GetFieldCont xname Record 1
maxx = minx = Result

F_GetFieldCont yname Record 1
maxy = miny = Result

do i = 1 to num

    F_Progress i num

    F_GetFieldCont xname Record i
    if result > maxx then maxx = result
    if result < minx then minx = result

    F_GetFieldCont yname Record i
    if result > maxy then maxy = result
    if result < miny then miny = result

end

/*
 *  Dimensions of TeX graphic
 */

w = 320
h = 350

/*
 *  Values for scale
 */

scalebasex = 5
scalebasey = 5

/*
 *  Origin?
 */

orgoo = 1   /* (0;0) */

/*
 *  Advanced options menu
 */

done = 0

do while ~done

    F_RequestChoice '"Advanced Options Menu:*n1 - Edit Scale Base*n2 - Edit Origin*n3 - Edit Axis Labels*n4 - Edit Point Marker" "Continue|1|2|3|4|Cancel"'

    if result = 1 then
    do

        done = 1

    end
    else if result = 2 then
    do

        F_RequestNumber scalebasex 'Text "Please input scale base for x axis"'
        if rc = 0 then scalebasex = result

        F_RequestNumber scalebasey 'Text "Please input scale base for y axis"'
        if rc = 0 then scalebasey = result

    end
    else if result = 3 then
    do

        F_RequestChoice '"What origin do you want to use?"' '"(0;0)|project specific"'
        if result = 1 then orgoo = 1
        else orgoo = 0

    end
    else if result = 4 then
    do

        F_RequestString '"' || xlabel || '"' Text '"Edit label for x axis:"'
        if rc = 0 then xlabel = result

        F_RequestString '"' || ylabel || '"' Text '"Edit label for y axis:"'
        if rc = 0 then ylabel = result

    end
    else if result = 5 then
    do

        F_RequestString '"' || cross || '"' Text '"Edit marker for specified points:*n(Empty input will result in no marker)"'
        if rc = 0 then cross = result

    end
    else
    do

        call bailout

    end

end

if orgoo = 1 then do

    if minx > 0 then minx = 0
    if miny > 0 then miny = 0

end

/*
 *  Calculate the space that the graphic requires
 */

realw = abs(maxx - minx)
realh = abs(maxy - miny)

/*
 * Calculate values which can be used to
 * convert the "real world" values to
 * TeX conform values
 */

xfact = w / (realw) * 0.95
yfact = h / (realh) * 0.95

xabs = -(minx * xfact);
yabs = -(miny * yfact);

/*
 * Look whether the axes may have a zero position
 */

xaxisnull = maxx >= 0 & minx <= 0
yaxisnull = maxy >= 0 & miny <= 0

if yaxisnull | orgoo then
    xaxisy = 0
else
    xaxisy = miny

if xaxisnull | orgoo then
    yaxisx = 0
else
    yaxisx = minx

F_SetStatus '"Creating file..."'

/*
 * Open file
 */

if ~open("file", texfile, "write") then do

    F_RequestChoice '"Could not open*n' || texfile || '"' '"Cancel"'

    call bailout

end

/*
 * write file header
 */

if completefile = 1 then
    call writeln("file", "\documentstyle[epic,eepic]{article} \begin{document}")

call writeln("file", "% This document has been created by Fiasco Release 2.0")
call writeln("file", "% and GraphPrint.rexx Release 2.0 by Nils Bandener.")

call writeln("file", "\begin{picture}(" || w || "," || h || ")(0, 0) \linethickness{0.15mm}")

/*
 * Draw arrows
 */

call writeln("file", "\put(" || 0 || "," || xaxisy * yfact + yabs || "){\vector(1,0){" || w || "}}")

call writeln("file", "\put(" || yaxisx * xfact + xabs || "," || 0 || "){\vector(0,1){" || h || "}}")

/*
 * Put field IDs at arrows
 */

call writeln("file", "\put(" || w + 10 || ", " || xaxisy * yfact + yabs || "){ \makebox(0,0){" || xlabel || "}}")

call writeln("file", "\put(" || yaxisx * xfact + xabs || "," || h + 10 || "){ \makebox(0,0){" || ylabel || "}}")

/*
 * Calculate best scaling for max-values
 */

/*
 * This emulates log base 5:
 *
 * b log x = ln x / ln b
 */

if scalebasex <= 1 then scalebasex = 10

ptx = int(ln(realw)/ln(scalebasex)-1)

if scalebasey <= 1 then scalebasey = 10

pty = int(ln(realh)/ln(scalebasey)-1)

contloop = 1

/*
 *  calculate good values for scala
 */

do while contloop

    xscale = pow(scalebasex,ptx)
    yscale = pow(scalebasey,pty)

    xscalenum = trunc(realw / xscale * 1.05 + .5)
    yscalenum = trunc(realh / yscale * 1.05 + .5)

    contloop = 0

    if xscalenum > 30 then do

        ptx = ptx + 1
        contloop = 1

    end

    if yscalenum > 30 then do

        pty = pty + 1
        contloop = 1

    end
end

/*
 *  Draw scala on x axis
 */

startval = trunc(minx / xscale) * xscale

do forever

    coord = startval * xfact + xabs

    if coord < 0 then startval = startval + xscale / 2
    else break

end

call writeln("file", "\multiput(" || coord || ", " || xaxisy * yfact - 1 + yabs || ")(" || xscale * xfact / 2 || ",0){" || xscalenum * 2 - 1 || "}{\line(0,1){2}}")

numbers = ""

places = -trunc(log10(xscale))
if places < 0 then places = 0

curval = startval

do i = 1 to xscalenum

    if curval = 0 then
        numbers = numbers || " "
    else
        numbers = numbers || trunc(curval, places)

    curval = curval + xscale

    if i ~= xscalenum then numbers = numbers || ", "

end

call writeln("file", "\multiputlist(" || coord || "," || xaxisy * yfact - 8 + yabs || ")(" || xscale * xfact || ",0){" || numbers || "}")

/*
 *  Draw scala on y axis
 */

startval = trunc(miny / yscale) * yscale

do forever

    coord = startval * yfact + yabs

    if coord < 0 then startval = startval + yscale / 2
    else break

end

call writeln("file", "\multiput(" || yaxisx * xfact - 1 + xabs || ", " || coord || ")(0," || yscale * yfact / 2 || "){" || yscalenum * 2 - 1 || "}{\line(1,0){2}}")

numbers = ""

places = -trunc(log10(yscale))
if places < 0 then places = 0

curval = startval

do i = 1 to yscalenum

    if curval = 0 then
        numbers = numbers || " "
    else
        numbers = numbers || trunc(curval, places)

    curval = curval + yscale

    if i ~= yscalenum then numbers = numbers || ", "

end

call writeln("file", "\multiputlist(" || yaxisx * xfact - 12 + xabs || ", " || coord || ")(0," || yscale * yfact || "){" || numbers || "}")

/*
 *  Draw graphic
 */

call writeln("file", "\begin{drawjoin} \thinlines")

do i = 1 to num

    F_Progress i num

    F_GetFieldCont xname Record i
    xvalue = result

    F_GetFieldCont yname Record i
    yvalue = result

    call writeln("file", "\jput(" || xvalue * xfact + xabs || ", " || yvalue * yfact + yabs || "){ " || cross || "}")

    /*
     * Put the field ID at the graph
     *
     * This would be useful for diagrams with several graphs,
     * not used now
     *

    if i = num then do

        call writeln("file", "\put(" || xvalue * xfact + 15 + xabs || ", " || yvalue * yfact + yabs || "){ " || xname || " }")

    end

     */
end


call writeln("file", "\end{drawjoin}")

call writeln("file", "\end{picture}")

if completefile = 1 then
    call writeln("file", "\end{document}")

call close("file")

/*
 *  If Print has been selected, do the job
 */

if desttype = 0 then do

    F_SetStatus '"virtex..."'

    Address COMMAND

    'tex:bin/virtex &latex' '"' || texfile || '"'

    /*
     *  Should check for errors here
     */

    dotpos = lastpos(".", texfile)

    if dotpos ~= 0 then namebody = substr(texfile, 1, dotpos-1)
    else namebody = texfile

    dvifile = namebody || ".dvi"

    finished = 0

    /*
     *  Look for the port of special host
     *  If not present, ask whether the user
     *  wants to start special host
     */

    specialhost_started = 0

    if ~show("Ports","special_dvi") then do

        Address FIASCO

        F_RequestChoice Title '"Graph Print"' '"Special Host is not running!*nDo you want me to start it?*n(Special Host is required for*nprinting and displaying of the data)"' '"Yes|No"'

        if result = 1 then do

            Address COMMAND "run >nil: <nil: tex:bin/specialhost nogui"
            specialhost_started = 1

        end
    end

    do while ~finished

        Address FIASCO
        F_ResetStatus

        F_RequestChoice Title '"Menu"' '"Do you want to view the file, print it or quit?"' '"View|Print|Quit"'
        choice = result

        if choice = 1 then do

            F_SetStatus '"showdvi..."'

            Address COMMAND

            'tex:bin/showdvi' '"' || DVIFile || '"'

        end
        else if choice = 2 then do

            F_SetStatus '"dviprint..."'

            Address COMMAND

            'tex:bin/dviprint' '"' || DVIFile || '"'

        end
        else finished = 1

    end

    /*
     *  If this script has started Special Host,
     *  ask the user, whether he wants the script
     *  to break the program
     */

    if specialhost_started then do

        Address FIASCO

        F_RequestChoice Title '"Graph Print"' '"Do you want to terminate Special Host?"' '"Yes|No"'

        if result = 1 then do

            Address COMMAND "break `status com tex:bin/specialhost`"

        end
    end

    call Delete(texfile)
    call Delete(DVIFile)
    call Delete(DVIFile || ".info")
    call Delete(namebody || ".log")
    call Delete(namebody || ".aux")

end

call bailout

/*
 *  Procedures
 */


/*
 *  bailout
 *
 *  Clean up and exit the script
 */

bailout:

Address FIASCO
F_ResetStatus
F_UnlockGUI

exit

syntax:
failure:
say "Error" rc "in line" sigl ":" errortext(rc)

halt:
break_c:
say "Break"
say "Enter to continue"

pull dummy

call bailout
