Logo Search packages:      
Sourcecode: nase-a60 version File versions

xa60.c

/*
 * Simple X11 edit-and-go frontend for the NASE A60 interpreter.
 * Copyright (C) 1991-1996 Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de)
 *
 * This file is part of NASE A60.
 * 
 * NASE A60 is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * NASE A60 is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NASE A60; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * xa60.c:                                may 1991
 *
 * first steps to a simple X frontend for edit and go fun.
 * (nothing serious - be warned)
 */

#include <stdio.h>

#ifdef USG
#ifndef SYSV
/* commonly expected by X11R4: */
#define SYSV
#endif /* ! SYSV */
#endif /* USG */

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Box.h>

#define VERSION         "xa60  v0.12,  March 1996"

#define A60PATH         "a60"
#define A60FLAGS  "-X"

/*
 * define as 1 to include a save button; this is not necessary,
 * because the text is saved before every execution. (and upon exit) 
 */
#define SAVE_BUTTEN     0


static String fallback_resources [] = { 
    "*input:                  True",
    "*showGrip:         on",
    "*paned.width:            560",

    "*etext*height:           360", 
    "*etext*editType:         edit",
    "*etext*scrollVertical:   whenNeeded",
    "*etext*autoFill:         on",

    "*otext*height:           240", 
    "*otext*editType:         append",
    "*otext*scrollVertical:   whenNeeded",
    "*otext*wrap:       line",
    "*otext*displayCaret:     False",

    "*bexit*label:            Exit",
    "*bexit*shapeStyle:       oval",
    "*bexit*borderWidth:      2",

    "*clear*label:            Clear",
    "*clear*shapeStyle:       oval",
#if SAVE_BUTTEN
    "*save*label:             Save",
    "*save*shapeStyle:        oval",
#endif
    "*go*label:         Go",
    "*go*shapeStyle:          oval",

    "*fnlab*borderWidth:      0",

    NULL,
};


/* selected input file: */
static char *fname = (char *) 0;

/* temporary textbuffer (and its length): */
static char *txt_buf = (char *) 0;
static int txt_max = 0;
static int txt_len;

/* global ... */
static Widget etext, otext;

/* forward: */
static void have_a_run ();


/*
 * create a temporary file; a simple name is enough.
 * static storage is ok.
 */

static char *
mk_fname ()
{
      static char tmp [128];

      sprintf (tmp, "/tmp/nase-%d", getpid ());

      return tmp;
}


static void
read_file ()
{
      FILE *fp;
      int ch;
      
      fp = fopen (fname, "r");

      if (! fp) {
            fp = fopen (fname, "w");
            if (! fp) {
                  fprintf (stderr, "cannot open `%s' for writing...\n",
                         fname);
                  exit (1);
            }

            /*
             * insert some default text:
             */
      
            fprintf (fp, "begin\n    vprint (\"Hi!\")\nend\n");
            fclose (fp);

            fp = fopen (fname, "r");
      }

      if (! fp) {
            fprintf (stderr, "cannot open `%s' for reading...\n",
                   fname);
            exit (1);
      }

      txt_len = 0;

      do {
            if (txt_len + 10 > txt_max) {
                  txt_max += 1000;
                  if (! txt_buf)
                        txt_buf = XtMalloc (txt_max);
                  else
                        txt_buf = XtRealloc (txt_buf, txt_max);
            }
            
            ch = fgetc (fp);

            if (ch != EOF)
                  txt_buf [txt_len++] = ch;
      } while (ch != EOF);

      txt_buf [txt_len] = 0;

      fclose (fp);
}


static void
append_text (w, str)
Widget w;
char *str;
{
      XawTextBlock tb;
      int rc, point;
      
      tb.firstPos = 0;
      tb.length = strlen (str);
      tb.ptr = str;
      tb.format = FMT8BIT;
      
      point = XawTextGetInsertionPoint (w);

      rc = XawTextReplace (w, point, point, &tb);
      
      XawTextSetInsertionPoint (w, point + strlen (str));

      if (rc == XawPositionError)
            printf ("** xa60 internal error: XawPositionError ...\n");
      else if (rc == XawEditError)
            printf ("** xa60 internal error: XawEditError ...\n");
}


static void
set_caret (lno)
int lno;
{
      Arg args[1];
      String str;
      int i, n;

      XtSetArg(args[0], XtNstring, &str);
      XtGetValues(etext, args, ONE);


      /* look for character position of line lno : */

      for (n = 0, i = 1; str [n] && i < lno; n++)
            i += str [n] == '\n';

      XawTextSetInsertionPoint (etext, n);
}

/*
 * saving the text means: print the string (which contains the
 * complete text).
 * If this fails - abort.
 */

static void
save_file (txt)
char *txt;
{
      FILE *fp;

      fp = fopen (fname, "w");
      if (! fp) {
            fprintf (stderr, "cannot open `%s' for writing...\n",
                   fname);
            exit (1);
      }

      fprintf (fp, "%s\n", txt);
      fclose (fp);
}


/*
 * The callbacks for the Three buttons:  Exit, Clear, Save and Go:
 */

/* ARGSUSED */
static void
cb_clear (w, text_ptr, call_data)
Widget w;
XtPointer text_ptr, call_data;
{
      Widget text = (Widget) text_ptr;
      Arg args[1];
      
      XtSetArg (args[0], XtNstring, "");
      XtSetValues (text, args, ONE);
}


/* ARGSUSED */
static void
cb_save (w, text_ptr, call_data)
Widget w;
XtPointer text_ptr, call_data;
{
      Widget text = (Widget) text_ptr;
      Arg args[1];
      String str;

      XtSetArg(args[0], XtNstring, &str);
      XtGetValues(text, args, ONE);

      save_file (str);
}


/* ARGSUSED */
static void
cb_bexit (w, text_ptr, call_data)
Widget w;
XtPointer text_ptr, call_data;
{
      cb_save (w, text_ptr, call_data);
      
      exit (0);
}


/* ARGSUSED */
static void
cb_go (w, text_ptr, call_data)
Widget w;
XtPointer text_ptr, call_data;
{
      cb_save (w, text_ptr, call_data);

      have_a_run ();
}


/*
 * Try to get a linenumber from this line: error lines are looking like:
 * nase.a60: 12: parse error
 * return the linenumber or return a 0.
 */

static int
is_error_line (s)
char *s;
{
      int lno = 0;

      int len = strlen (fname);

      if (! strncmp (fname, s, len) && s [len] == ':')
            lno = atoi (s + len + 1);

      return lno;
}


/*
 * read the lines from fp look about an error message (to set the
 * caret [cursor]) and append the line to the output.
 */

static void
process_a60 (fp)
FILE *fp;
{
      char buf [1024];              /* fixed length :-( */
      int cursor_set = 0, lno;

      while (buf == fgets (buf, 1024, fp)) {
            append_text (otext, buf);

            if (! cursor_set) {
                  lno = is_error_line (buf);
                  if (lno) {
                        set_caret (lno);
                        cursor_set = 1;
                  }
            }
      }
}


/*
 * process the buffer through a60. a single directional pipe is enough
 * and i'll use popen.
 * (may be a fork providing a stdin from this process would be nice)
 */

static void
have_a_run ()
{
      FILE *fp;
      char cmd [100];
      char tmp [100];

      sprintf (cmd, "%s %s %s", A60PATH, A60FLAGS, fname);
      fp = popen (cmd, "r");

      if (! fp) {
            sprintf (tmp, "cannot execute `%s'.\n", cmd);
            append_text (otext, tmp);
      }
      else {
            sprintf (tmp, "*** a60 starting:\n");
            append_text (otext, tmp);
            process_a60 (fp);
            pclose (fp);
            append_text (otext, "*** a60 done.\n\n");
      }
}



static void 
usage ()
{
      fprintf (stderr, "Use:  xa60  [ -V ] | [ <source file> ]\n");
      
      exit (1);
}


/*
 * M A I N
 */

int
main (argc, argv)
int argc;
char *argv[];
{
      XtAppContext app_con;
      Widget toplevel, paned, box, clear, bexit, go;
      Arg args[1];
      char *fn_str;
#if SAVE_BUTTEN
      Widget save;
#endif

      toplevel = XtAppInitialize (&app_con, "XA60", NULL, ZERO,
                     &argc, argv, fallback_resources, NULL, ZERO);

      /*
       * Check to see that all arguments were processed, and if not then
       * report an error and exit.
       */
      
      if (argc > 2)
            usage ();

      if (argc == 2) 
      {
            if (! strcmp (argv [1], "-V")) 
            {
                  printf ("Version:  %s.\n", VERSION);
                  exit (0);
            }
            else if (! strcmp (argv [1], "-h")) 
            {
                  usage ();
            }
            else {
                  fname = argv [1];
            }
      }
      else {
            fname = mk_fname ();
      }

      fn_str = XtMalloc (strlen (fname) + 20);
      sprintf (fn_str, " File: %s", fname);

      read_file ();
      
      paned = XtCreateManagedWidget ("paned", panedWidgetClass, toplevel, 
                               NULL, ZERO);
      
      box = XtCreateManagedWidget ("box", boxWidgetClass, paned, 
                             NULL, ZERO);
      
      bexit = XtCreateManagedWidget ("bexit", commandWidgetClass, box, 
                               NULL, ZERO);
      
      clear = XtCreateManagedWidget ("clear", commandWidgetClass, box, 
                               NULL, ZERO);
#if SAVE_BUTTEN
      save = XtCreateManagedWidget ("save", commandWidgetClass, box, 
                              NULL, ZERO);
#endif
      go = XtCreateManagedWidget ("go", commandWidgetClass, box, 
                            NULL, ZERO);

      XtSetArg (args[0], XtNlabel, fn_str);
      XtCreateManagedWidget ("fnlab", labelWidgetClass, box, args, ONE);

      XtSetArg (args[0], XtNstring, txt_buf);
      etext = XtCreateManagedWidget ("etext", asciiTextWidgetClass, paned, 
                             args, ONE);

      XtSetArg (args[0], XtNstring, "See:\n");
      otext = XtCreateManagedWidget ("otext", asciiTextWidgetClass, paned, 
                              args, ONE);

      XtAddCallback (bexit, XtNcallback, cb_bexit, (XtPointer) etext);
      XtAddCallback (clear, XtNcallback, cb_clear, (XtPointer) etext);
#if SAVE_BUTTEN
      XtAddCallback (save, XtNcallback, cb_save, (XtPointer) etext);
#endif
      XtAddCallback (go, XtNcallback, cb_go, (XtPointer) etext);

      XtRealizeWidget (toplevel);
      XtAppMainLoop (app_con);

      /* not reached */
      return 0;
}

/* end of xa60.c */


Generated by  Doxygen 1.6.0   Back to index