Logo Search packages:      
Sourcecode: malaga version File versions  Download package

malshow.c

/* Copyright (C) 1995 Bjoern Beutel. */

/* Description. =============================================================*/

/* This is a GTK program that displays Malaga values. */

/* Includes. ================================================================*/

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <setjmp.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <locale.h>
#include <gtk/gtk.h>
#include "basic.h"
#include "input.h"
#include "scanner.h"
#include "files.h"
#include "canvas.h"
#include "allomorphs.h"
#include "expressions.h"
#include "result.h"
#include "tree.h"
#include "variables.h"
#ifdef UNIX
#include <unistd.h>
#endif

/* Variables. ===============================================================*/

#ifdef WINDOWS
static bool_t input_consumed; /* Set by consumer, reset by pipe thread. */
static GCond *input_consumed_cond; /* Signals that "input_consumed" is set. */
static GMutex *input_consumed_mutex;
#endif

/* Functions. ===============================================================*/

static void 
parse_font_size( string_t input, int_t *font_size )
{
  int_t size;

  size = parse_int( &input );
  parse_end( &input );
  if (size != 8 && size != 10 && size != 12 && size != 14 && size != 18
      && size != 24)
  {
    complain( "Illegal font size, valid sizes are 8, 10, 12, 14, 18, 24." );
  }
  *font_size = size;
}

/*---------------------------------------------------------------------------*/

static int_t 
my_parse_int( string_t *input_p )
/* Parse an integer number in *INPUT_P, adjust *INPUT_P.
 * Parsing stops when the first non-digit is encountered. */
{
  int_t number;
  string_t input;

  input = *input_p;
  if (! IS_DIGIT( *input )) 
    complain( "Number expected." );
  number = 0;
  while (IS_DIGIT( *input )) 
    number = 10 * number + (*input++ - '0');
  *input_p = input;
  return number;
}

/*---------------------------------------------------------------------------*/

static void 
parse_geometry( string_t input, rectangle_t *geometry )
{ 
  static char_t malformed[] = "Malformed geometry.";
  string_t arg, arg_p;
  
  arg_p = arg = parse_word( &input );
  parse_end( &input );

  if (! IS_DIGIT( *arg_p ) && *arg_p != '+') 
    complain( malformed );
  if (IS_DIGIT( *arg_p ))
  { 
    /* Parse size. */
    geometry->width = my_parse_int( &arg_p );
    if (*arg_p != 'x') 
      complain( malformed );
    arg_p++;
    geometry->height = my_parse_int( &arg_p );
  }
  if (*arg_p == '+')
  { 
    /* Parse position. */
    arg_p++;
    geometry->x = my_parse_int( &arg_p );
    if (*arg_p != '+') 
      complain( malformed );
    arg_p++;
    geometry->y = my_parse_int( &arg_p );
  }
  if (*arg_p != EOS) 
    complain( malformed );
  free_mem( &arg );
}

/*---------------------------------------------------------------------------*/

static void 
read_profile( string_t file_name )
{
  FILE *stream;
  string_t line, line_p, argument;
  volatile int_t line_count;

  /* Initialise positions to be ignored. */
  allomorphs_geometry.x = allomorphs_geometry.y = -1;
  expressions_geometry.x = expressions_geometry.y = -1;
  path_geometry.x = path_geometry.y = -1;
  result_geometry.x = result_geometry.y = -1;
  tree_geometry.x = tree_geometry.y = -1;
  variables_geometry.x = variables_geometry.y = -1;

  stream = open_stream( file_name, "r" );
  line_count = 0;

  while (TRUE)
  {
    line = read_line( stream );
    if (line == NULL)
      break;
    line_count++;
    cut_comment( line );
    line_p = line;

    if (*line_p != EOS)
    {
      argument = NULL;
      TRY
      {
      argument = parse_word( &line_p );
      if (strcmp_no_case( argument, "allomorphs_geometry:" ) == 0)
        parse_geometry( line_p, &allomorphs_geometry );
      else if (strcmp_no_case( argument, "expressions_geometry:" ) == 0)
        parse_geometry( line_p, &expressions_geometry );
      else if (strcmp_no_case( argument, "path_geometry:" ) == 0)
        parse_geometry( line_p, &path_geometry );
      else if (strcmp_no_case( argument, "result_geometry:" ) == 0)
        parse_geometry( line_p, &result_geometry );
      else if (strcmp_no_case( argument, "tree_geometry:" ) == 0)
        parse_geometry( line_p, &tree_geometry );
      else if (strcmp_no_case( argument, "variables_geometry:" ) == 0)
        parse_geometry( line_p, &variables_geometry );
      else if (strcmp_no_case( argument, "font_size:" ) == 0)
        parse_font_size( line_p, &font_size );
      else if (strcmp_no_case( argument, "font:" ) == 0)
      {
        if (font_name != NULL) 
          complain( "font name already defined" );
        font_name = parse_word( &line_p );
        parse_end( &line_p );
      }
      }
      IF_ERROR
      {
        print_text( error_text, " (\"%s\", line %d)\n", 
                name_in_path( file_name ), line_count );
      }
      FINALLY 
      free_mem( &argument );
      END_TRY;
    }
    free_mem( &line );
  }
  close_stream( &stream, file_name );
}

/*---------------------------------------------------------------------------*/

static void
read_input( string_t input_type )
/* Read and show INPUT_TYPE from STDIN. */
{
  if (strcmp_no_case( input_type, "allomorph" ) == 0) 
    read_allomorphs();
  else if (strcmp_no_case( input_type, "expressions" ) == 0) 
    read_expressions();
  else if (strcmp_no_case( input_type, "result" ) == 0) 
    read_result();
  else if (strcmp_no_case( input_type, "tree" ) == 0) 
    read_tree();
  else if (strcmp_no_case( input_type, "variables" ) == 0) 
    read_variables();
}

/*---------------------------------------------------------------------------*/

#ifdef UNIX
static void
read_on_condition( gpointer data, gint source, GdkInputCondition condition )
/* This is called by GDK whenever there is something to read. 
 * It reads input from malaga and displays the appropriate canvas. */
{
  string_t input_type;
  
  input_type = read_line( stdin );
  if (input_type == NULL) 
    gtk_exit(0);
  read_input( input_type );
  free_mem( &input_type );
}
#endif

/*---------------------------------------------------------------------------*/


#ifdef WINDOWS
static bool_t
read_input_notify( string_t input_type )
/* Read INPUT_TYPE from stdin, display it, and notify waiting thread. */ 
{
  if (input_type == NULL) 
    gtk_exit(0);
  read_input( input_type );
  g_mutex_lock( input_consumed_mutex );
  input_consumed = TRUE;
  g_cond_signal( input_consumed_cond );
  g_mutex_unlock( input_consumed_mutex );
  return FALSE;
}
#endif

/*---------------------------------------------------------------------------*/

#ifdef WINDOWS
static void *
input_thread( void *dummy )
/* Read one line from STDIN, inform main thread when new input has arrived. */
{
  string_t input_type;

  while (TRUE)
  {
    input_type = read_line( stdin );
    g_idle_add( (GSourceFunc) read_input_notify, input_type );
    g_mutex_lock( input_consumed_mutex );
    while (! input_consumed)
      g_cond_wait( input_consumed_cond, input_consumed_mutex );
    input_consumed = FALSE;
    g_mutex_unlock( input_consumed_mutex );
    free_mem( &input_type );
  }
  return NULL;
}
#endif

/*---------------------------------------------------------------------------*/

int 
main( int argc, char *argv[] )
{
  string_t malagarc_path, input_type;

  init_basic( "malshow" );
  init_input();
  init_scanner();

  if (argc == 2) 
  { 
    if (strcmp_no_case( argv[1], "--version" ) == 0
      || strcmp_no_case( argv[1], "-version" ) == 0
      || strcmp_no_case( argv[1], "-v" ) == 0) 
    { 
      program_message();
      exit(0);
    } 
    else if (strcmp_no_case( argv[1], "--help" ) == 0
           || strcmp_no_case( argv[1], "-help" ) == 0
           || strcmp_no_case( argv[1], "-h" ) == 0) 
    { 
      printf( "Display results of a Malaga process in a graphical format.\n\n"
            "Usage:\n"
            "malshow            -- Display results from malaga.\n"
            "malshow -v[ersion] -- Print the version number.\n"
            "malshow -h[elp]    -- Print this help.\n\n"
            "This program is usually started by malaga.\n" );
      exit(0);
    }
  }

  gtk_init( &argc, &argv );
  /* "gtk_init" might set LC_NUMERIC, so we reset it to POSIX defaults. */
  setlocale( LC_NUMERIC, "POSIX" );

  /* Read Malaga profile. */
  malagarc_path = NULL;
#ifdef UNIX
  TRY 
    malagarc_path = absolute_path( "~/.malagarc", NULL );
  IF_ERROR 
    RESUME;
  END_TRY;
#endif
#ifdef WINDOWS
  TRY 
    malagarc_path = absolute_path( "~\\malaga.ini", NULL );
  IF_ERROR 
    RESUME;
  END_TRY;
#endif
  if (malagarc_path != NULL && file_exists( malagarc_path ))
    read_profile( malagarc_path );
  free_mem( &malagarc_path );

  /* Determine character set. */
  char_set = read_line( stdin );
  if (char_set == NULL) 
    complain( "Premature EOF." );
  if (strcmp_no_case( char_set, "hangul" ) == 0)
  {
    hangul = TRUE;
    free_mem( &char_set );
    char_set = new_string( "*-*", NULL );
  }
  else 
    hangul = FALSE;

  /* Determine font name. */
  if (font_name == NULL)
  {
#ifdef UNIX
    font_name = new_string( "helvetica", NULL );
#endif
#ifdef WINDOWS
    if (hangul) 
      font_name = new_string( "Dotum", NULL );
    else 
      font_name = new_string( "Arial", NULL );
#endif
  }
  
  /* Read first input. */
  input_type = read_line( stdin );
  read_input( input_type );
  free_mem( &input_type );

  /* Prepare to read again whenever there is new input. */
#ifdef UNIX
  gdk_input_add( STDIN_FILENO, GDK_INPUT_READ, read_on_condition, NULL );
#endif
#ifdef WINDOWS
  g_thread_init( NULL );
  input_consumed_cond = g_cond_new();
  input_consumed_mutex = g_mutex_new();
  g_thread_create( input_thread, NULL, FALSE, NULL );
#endif

  gtk_main();

  free_mem( &char_set );
  free_mem( &font_name );
  terminate_scanner();
  terminate_input();
  terminate_basic();
  return 0;
}

/* End of file. =============================================================*/

Generated by  Doxygen 1.6.0   Back to index