/* Written by Dan Heller and Paula Ferguson.  
 * Copyright 1994, O'Reilly & Associates, Inc.
 * Permission to use, copy, and modify this program without
 * restriction is hereby granted, as long as this copyright
 * notice appears in each copy of the program source code.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warrantee expressed or implied.
 * This program is -not- in the public domain.
 */

/* cmd_area.c -- use a ScrolledText object to view the
 * output of commands input by the user in a Command window.
 */
#include  <Xm/Text.h>
#include  <Xm/MainW.h>
#include  <Xm/Command.h>
#include  <stdio.h>         /* For popen() */

void
Exit(drawing_a, client_data, call_data)
Widget    drawing_a;
XtPointer client_data;
XtPointer call_data;
{
  exit(0);
}

/* main() -- initialize toolkit, create a main window, menubar,
 * a Command Area and a ScrolledText to view the output of commands.
 */
main(argc, argv)
int argc;
char *argv[];
{
    Widget        top, main_w, menubar, menu, command_w, text_w;
    XtAppContext  app;
    XmString      file, quit;
    extern void   exec_cmd(), exit();
    Arg           args[5];
    int           n = 0;

    XtSetLanguageProc (NULL, NULL, NULL);

    /* initialize toolkit and create toplevel shell */
    top = XtVaAppInitialize (&app, "Demos",
        NULL, 0, &argc, argv, NULL, NULL);

    (void) close (0); /* don't let commands read from stdin */

    /* MainWindow for the application -- contains menubar, ScrolledText
     * and CommandArea (which prompts for filename).
     */
    main_w = XtVaCreateManagedWidget ("main_w",
        xmMainWindowWidgetClass, top,
        XmNcommandWindowLocation, XmCOMMAND_BELOW_WORKSPACE,
        NULL);

    /* Create a simple MenuBar that contains one menu */
    file = XmStringCreateLocalized ("File");
    menubar = XmVaCreateSimpleMenuBar (main_w, "menubar",
        XmVaCASCADEBUTTON, file, 'F',
        NULL);
    XmStringFree (file);

    /* "File" menu has only one item (Quit), so make callback exit() */
    quit = XmStringCreateLocalized ("Quit");
    /* menu = XmVaCreateSimplePulldownMenu (menubar, "file_menu", 0, exit, */
    menu = XmVaCreateSimplePulldownMenu (menubar, "file_menu", 0, Exit,
        XmVaPUSHBUTTON, quit, 'Q', NULL, NULL,
        NULL);
    XmStringFree (quit);

    /* Menubar is done -- manage it */
    XtManageChild (menubar);

    /* Create ScrolledText -- this is work area for the MainWindow */
    XtSetArg (args[n], XmNrows,      24); n++;
    XtSetArg (args[n], XmNcolumns,   80); n++;
    XtSetArg (args[n], XmNeditable,  False); n++;
    XtSetArg (args[n], XmNeditMode,  XmMULTI_LINE_EDIT); n++;
    text_w = XmCreateScrolledText (main_w, "text_w", args, n);
    XtManageChild (text_w);

    /* store text_w as user data in "File" menu for file_cb() callback */
    XtVaSetValues (menu, XmNuserData, text_w, NULL);

    /* Create the command area -- this must be a Command class widget */
    file = XmStringCreateLocalized ("Command:");
    command_w = XtVaCreateWidget ("command_w", xmCommandWidgetClass, main_w,
        XmNpromptString, file,
        NULL);
    XmStringFree (file);
    XtAddCallback (command_w, XmNcommandEnteredCallback, exec_cmd, text_w);
    XtManageChild (command_w);

    XmMainWindowSetAreas (main_w, menubar, command_w,
        NULL, NULL, XtParent (text_w));
    XtRealizeWidget (top);
    XtAppMainLoop (app);
}

/* execute the command and redirect output to the ScrolledText window */
void
exec_cmd (cmd_widget, client_data, call_data)
Widget cmd_widget;  /* the command widget itself, not its Text widget */
XtPointer client_data; /* passed the text_w as client_data */
XtPointer call_data;
{
    char *cmd, buf[BUFSIZ];
    XmTextPosition pos;
    FILE *pp, *popen();
    Widget text_w = (Widget) client_data;
    XmCommandCallbackStruct *cbs = 
        (XmCommandCallbackStruct *) call_data;

    XmStringGetLtoR (cbs->value, XmFONTLIST_DEFAULT_TAG, &cmd);

    if (!cmd || !*cmd) { /* nothing typed? */
        if (cmd)
            XtFree (cmd);
        return;
    }

    /* make sure the file is a regular text file and open it */
    if (!(pp = popen (cmd, "r")))
        perror (cmd);
    XtFree (cmd);
    if (!pp)
        return;

    /* put the output of the command in the Text widget by reading
     * until EOF (meaning that the command has terminated).
     */
    for (pos = 0; fgets (buf, sizeof(buf), pp); pos += strlen (buf))
        XmTextReplace (text_w, pos, pos, buf);

    pclose (pp);
}