affbe5f5创建于 2025年3月25日历史提交
#include "ngspice/ngspice.h"
#include "ngspice/defines.h"
#include "ngspice/bool.h"
#include "ngspice/wordlist.h"
#include "ngspice/cpdefs.h"
#include "ngspice/fteinput.h"
#include "ngspice/ftedev.h"
#include "ngspice/ftedbgra.h"

#include "plotting/plotit.h"
#include "plotting/graphdb.h"
#include "plotting/graf.h"
#include "../misc/mktemp.h"

#include "arg.h"
#include "display.h"
#include "com_hardcopy.h"
#include "variable.h"


/* hardcopy file plotargs, or 'hardcopy file' -- with no other args
 * this prompts the user for a window to dump to a plot file. XXX no
 * it doesn't.  */
void com_hardcopy(wordlist *wl)
{
    char *fname = NULL;
    size_t n_byte_fname; /* size of fname in bytes, including null */
    char buf[BSIZE_SP], device[BSIZE_SP];
    bool tempf = FALSE;
    char *devtype;
#if defined(SYSTEM_PLOT5LPR) || defined(SYSTEM_PSLPR)
    char format[513];
#endif
    int printed;
    int hc_button;
    int foundit;

    static int n;

    if (!cp_getvar("hcopydev", CP_STRING, device, sizeof(device)))
        *device = '\0';

    if (!cp_getvar("hcopydevtype", CP_STRING, buf, sizeof(buf))) {
        devtype = "postscript";
    }
    else {
        devtype = buf;
    }

    if (wl) {
        hc_button = 0;
        fname = copy(wl->wl_word);
        n_byte_fname = (strlen(fname) + 1) * sizeof *fname;
        wl = wl->wl_next;
    }
    else {
        hc_button = 1;
        fname = smktemp2("hc", n);
        n++;
        tempf = TRUE;
        n_byte_fname = (strlen(fname) + 1) * sizeof *fname;
        if (!strcmp(devtype, "svg")) {
            fname = trealloc(fname, n_byte_fname + 4);
            (void)memcpy(fname + n_byte_fname - 1, ".svg", 5);
            n_byte_fname += 4;
        }
        else if (!strcmp(devtype, "postscript")) {
            fname = trealloc(fname, n_byte_fname + 3);
            (void)memcpy(fname + n_byte_fname - 1, ".ps", 4);
            n_byte_fname += 3;
        }
    }

    /* enable screen plot selection for these display types */
    foundit = 0;

#ifdef HAS_WINGUI
    if (!wl && hc_button) {
        char *psfname;
        GRAPH *tempgraph;
        /* initialze PS by calling PS_Init() */
        if (DevSwitch(devtype))
            return;
        if (currentgraph)
            tempgraph = CopyGraph(currentgraph);
        else {
            fprintf(stderr,
                    "No parameters for hardcopy command, not previous plot:\n");
            fprintf(stderr, "    Command hardcopy cannot be executed\n\n");
            DevSwitch(NULL);
            return;
        }

        if (!strcmp(devtype, "svg")) {
            /* change .tmp to .svg */
            psfname = strchr(fname, '.');
            if (psfname) {
                psfname[1] = 's';
                psfname[2] = 'v';
                psfname[3] = 'g';
                psfname[4] = '\0';
            }
            else {
                fname = trealloc(fname, n_byte_fname + 4);
                (void)memcpy(fname + n_byte_fname - 1, ".svg", 5);
                n_byte_fname += 4;
            }
        }
        else {
            /* change .tmp to .ps */
            psfname = strchr(fname, '.');
            if (psfname) {
                psfname[1] = 'p';
                psfname[2] = 's';
                psfname[3] = '\0';
            }
            else {
                fname = trealloc(fname, n_byte_fname + 3);
                (void)memcpy(fname + n_byte_fname - 1, ".ps", 4);
                n_byte_fname += 3;
            }
        }
        tempgraph->devdep = copy(fname);
        tempgraph->n_byte_devdep = n_byte_fname;

        if (NewViewport(tempgraph)) {
            DevSwitch(NULL);
            return;
        }
        gr_resize(tempgraph);
        /* use DevFinalize to add final statement in file, "/> or "stroke"*/
        DevFinalize();
        DestroyGraph(tempgraph->graphid);
        DevSwitch(NULL);
        foundit = 1;
    }
#endif


#ifndef X_DISPLAY_MISSING
    if (!wl && hc_button) {
        REQUEST request;
        RESPONSE response;
        GRAPH *tempgraph;

        request.option = click_option;
        Input(&request, &response);
        if (response.option == error_option) {
            return;
        }

        if (response.reply.graph) {
            if (DevSwitch(devtype)) {
                return;
            }
            tempgraph = CopyGraph(response.reply.graph);
            tempgraph->devdep = copy(fname);
            tempgraph->n_byte_devdep = n_byte_fname;
            if (NewViewport(tempgraph)) {
                DevSwitch(NULL);
                return;
            }
            /* save current graphics context */
            PushGraphContext(currentgraph);
            currentgraph = tempgraph;
            /* some operations in gr_resize, gr_redraw, and DevSwitch
               will be done on currentgraph, not only on tempgraph */
            gr_resize(tempgraph);
            gr_redraw(tempgraph);
            DevSwitch(NULL);
            /* retrieve current graphics context */
            PopGraphContext();
            DestroyGraph(tempgraph->graphid);
            foundit = 1;
        }
    }

#endif

    /* save current graphics context, because plotit() will create a new
       currentgraph */
    PushGraphContext(currentgraph);

    if (!foundit) {
        if (!wl && cp_getvar("interactive", CP_BOOL, NULL, 0)) {
            char *buf2;
            outmenuprompt("which variable ? ");
            buf2 = prompt(cp_in);
            if (!buf2) {
                return;
            }
            wl = wl_cons(buf2, NULL);
            wl = process(wl);
        }

        if (DevSwitch(devtype)) {
            return;
        }

        if (!wl || !plotit(wl, fname, NULL)) {
            printf("com_hardcopy: graph not defined\n");
            DevSwitch(NULL);    /* remember to switch back */
            return;
        }

        DevSwitch(NULL);
    }

    printed = 0;

    if (*device) {
#ifdef SYSTEM_PLOT5LPR
        if (!strcmp(devtype, "plot5") || !strcmp(devtype, "MFB")) {
            if (!cp_getvar("lprplot5", CP_STRING, format, sizeof(format)))
                strcpy(format, SYSTEM_PLOT5LPR);
            (void) sprintf(buf, format, device, fname);
            if (system(buf) == -1) {
                fprintf(cp_out, "Printing %s on the %s printer failed.\n",
                        fname, device);
            }
            else {
                fprintf(cp_out, "Printing %s on the %s printer OK.\n",
                        fname, device);
                printed = 1;
            }
        }
#endif
#ifdef SYSTEM_PSLPR
        if (!printed && !strcmp(devtype, "postscript")) {
            /* note: check if that was a postscript printer XXX */
            if (!cp_getvar("lprps", CP_STRING, format, sizeof(format)))
                strcpy(format, SYSTEM_PSLPR);
            (void) sprintf(buf, format, device, fname);
            if (system(buf) == -1) {
                fprintf(cp_out, "Printing %s on the %s printer failed.\n",
                        fname, device);
            }
            else {
                fprintf(cp_out, "Printing %s on the %s printer OK.\n",
                        fname, device);
                printed = 1;
            }
        }
#endif
    }

    if (!printed) {
        if (!strcmp(devtype, "plot5")) {
            fprintf(cp_out,
                    "The file \"%s\" may be printed with the Unix \"plot\" command,\n",
                    fname);
            fprintf(cp_out,
                    "\tor by using the '-g' flag to the Unix lpr command.\n");
        }
        else if (!strcmp(devtype, "postscript")) {
            fprintf(cp_out,
                    "\nThe file \"%s\" may be printed on a postscript printer.\n",
                    fname);
        }
        else if (!strcmp(devtype, "svg")) {
            fprintf(cp_out,
                "\nThe file \"%s\" has the Scalable Vector Graphics format.\n",
                fname);
        }
        else if (!strcmp(devtype, "MFB")) {
            fprintf(cp_out,
                    "The file \"%s\" may be printed on a MFB device.\n",
                    fname);
        }
    }

    if (tempf && *device) {
        (void) unlink(fname);
    }

    tfree(fname);

    /* restore previous graphics context by retrieving the previous currentgraph */
    PopGraphContext();
} /* end of function com_hardcopy */