⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mixgtk_cmd_dispatcher.c

📁 汇编语言编程源代码
💻 C
字号:
/* -*-c-*- -------------- mixgtk_cmd_dispatcher.c : * Implementation of the functions declared in mixgtk_cmd_dispatcher.h * ------------------------------------------------------------------ *  Last change: Time-stamp: "2001-04-08 01:34:09 jao" * ------------------------------------------------------------------ * Copyright (C) 2001 Free Software Foundation, Inc. *   * This program 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 of the License, or * (at your option) any later version. *   * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *   */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <mixlib/mix.h>#ifdef HAVE_LIBHISTORY#  include <readline/history.h>#endif#ifdef MAKE_GUILE#  include <mixguile/mixguile.h>#endif#include <gdk/gdkkeysyms.h>#include <mixlib/mix_vm_command.h>#include "mixgtk_mixvm.h"#include "mixgtk_mixal.h"#include "mixgtk_config.h"#include "mixgtk_cmd_dispatcher.h"/* a mix vm command dispatcher */typedef struct mixgtk_dispatch_{  mix_vm_cmd_dispatcher_t *dispatcher; /* the underlying cmd dispatcher */  FILE *out;			/* the dispatcher's output file */  int fildes[2];		/* pipe for communication with the dispatcher */  GtkWidget *prompt;		/* the command prompt widget */  GtkWidget *log;		/* the dispatcher's messages echo area */  GtkWidget *status;		/* the status bar widget */  guint context;		/* context of the status bar messages */  gchar *last_file;} mixgtk_dispatch_data_t;static struct mixgtk_dispatch_ dis_data_ = {NULL};static GtkWidget *ext_dlg_ = NULL;static GtkWidget *ed_entry_ = NULL;static GtkWidget *asm_entry_ = NULL;static const gchar *ED_NAME_ = "editor_entry";static const gchar *ASM_NAME_ = "mixasm_entry";static const gchar *TITLE_FORMAT_ = "gmixvm - %s";static voidlog_command_ (mixgtk_dispatch_data_t *dis, const gchar *cmd){  gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL,"MIX> ", -1);  gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL, cmd, -1);  gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL, "\n", -1);#ifdef HAVE_LIBHISTORY  add_history ((char *)cmd);/*  history_search ((char *)cmd, 0); */  history_set_pos (history_base + history_length - 1);#endif}static voidflush_log_ (mixgtk_dispatch_data_t *dis){  enum {BLKSIZE = 100};  static gchar BUFFER[BLKSIZE];    ssize_t k;  fflush (dis->out);  while ((k = read (dis->fildes[0], BUFFER, BLKSIZE)) != 0)    {      if (k == -1 && errno != EINTR) break;      if (k != -1)	gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL,			 BUFFER, k);    }}/* hooks */static voidglobal_post_hook_ (mix_vm_cmd_dispatcher_t *dis,		   mix_vm_command_t cmd, const gchar *arg, gpointer data){  flush_log_ ((mixgtk_dispatch_data_t *)data);  mixgtk_mixvm_update_vm_widgets ();}static voidload_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,		 gpointer data){  static glong id = -1;   if (mix_vm_cmd_dispatcher_get_last_result (dis))    {      GtkWindow *mainw =	GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN));      if (dis_data_.last_file) g_free (dis_data_.last_file);      dis_data_.last_file = g_strdup_printf (TITLE_FORMAT_, arg);      gtk_window_set_title (mainw, dis_data_.last_file);      mixgtk_mixal_load_file ();      mixgtk_mixal_update ();      mixgtk_mixal_update_bp_all ();            if (id != -1)	gtk_statusbar_remove (GTK_STATUSBAR (dis_data_.status),			      dis_data_.context, (guint)id);      id =	gtk_statusbar_push (GTK_STATUSBAR (dis_data_.status), dis_data_.context,			    dis_data_.last_file);    }}static voidrun_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,		 gpointer data){  mixgtk_mixal_update ();}static voidnext_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,		 gpointer data){  mixgtk_mixal_update ();}static voidlinebp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,		gpointer data){  if (arg && strlen (arg)) mixgtk_mixal_update_bp_at_line (atoi (arg));}static voidaddrbp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,		gpointer data){  if (arg && strlen (arg)) mixgtk_mixal_update_bp_at_address (atoi (arg));}static voidallbp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,		  gpointer data){  mixgtk_mixal_update_bp_all ();}static voidinstall_hooks_ (void){  mix_vm_cmd_dispatcher_global_post_hook (dis_data_.dispatcher,					  global_post_hook_,					  (gpointer)(&dis_data_));  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_LOAD, load_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_RUN, run_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_NEXT, next_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_SBP, linebp_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_CBP, linebp_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_SBPA, addrbp_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_CBPA, addrbp_post_hook_,				   NULL);  mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,				   MIX_CMD_CABP, allbp_post_hook_,				   NULL);}/* configuration stuff */static const gchar *EDITOR_KEY_ = "Editor";static const gchar *MIXASM_KEY_ = "Mixasm";static voidread_config_ (void){  const gchar *editor = mixgtk_config_get (EDITOR_KEY_);  const gchar *assem = mixgtk_config_get (MIXASM_KEY_);  if (!editor)    {      static const gchar *ENV[] = {"MDK_EDITOR", "X_EDITOR", NULL};      gchar *edit = NULL;      int k = 0;      while (!edit && ENV[k]) edit = getenv (ENV[k++]);      if (edit) edit = g_strconcat (edit, " %s", NULL);      else edit = g_strdup ("xterm -e vi %s");      mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, edit);      g_free (edit);    }  else    {      mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, editor);    }  if (!assem) assem = "mixasm -g %s";  mix_vm_cmd_dispatcher_set_assembler (dis_data_.dispatcher, assem);}voidon_external_programs_activate (){  if (!ext_dlg_)    {      ext_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_EXTERNPROG_DIALOG);      g_return_if_fail (ext_dlg_ != NULL);      ed_entry_ = mixgtk_widget_factory_get_child_by_name	(MIXGTK_EXTERNPROG_DIALOG, ED_NAME_);      g_assert (ed_entry_);      asm_entry_ = mixgtk_widget_factory_get_child_by_name	(MIXGTK_EXTERNPROG_DIALOG, ASM_NAME_);      g_assert (asm_entry_);    }  gtk_entry_set_text (GTK_ENTRY (ed_entry_),		      mix_vm_cmd_dispatcher_get_editor (dis_data_.dispatcher));  gtk_entry_set_text (GTK_ENTRY (asm_entry_),		      mix_vm_cmd_dispatcher_get_assembler		      (dis_data_.dispatcher));  gtk_widget_show (ext_dlg_);}voidon_extern_cancel_button_clicked (){  gtk_widget_hide (ext_dlg_);}voidon_extern_ok_button_clicked (){  const gchar *value = gtk_entry_get_text (GTK_ENTRY (ed_entry_));  mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, value);  mixgtk_config_update (EDITOR_KEY_, value);  value = gtk_entry_get_text (GTK_ENTRY (asm_entry_));  mix_vm_cmd_dispatcher_set_assembler (dis_data_.dispatcher, value);  mixgtk_config_update (MIXASM_KEY_, value);  gtk_widget_hide (ext_dlg_);}/* initialise the command dispatcher */gbooleanmixgtk_cmd_dispatcher_init (mixgtk_dialog_id_t top){  static gboolean restart = FALSE;  gchar *text = NULL;  ext_dlg_ = NULL;  ed_entry_ = NULL;  asm_entry_ = NULL;  dis_data_.prompt =    mixgtk_widget_factory_get (top, MIXGTK_WIDGET_PROMPT);  g_return_val_if_fail (dis_data_.prompt != NULL, FALSE);    if (dis_data_.log)    text = gtk_editable_get_chars (GTK_EDITABLE (dis_data_.log), 0, -1);    dis_data_.log =    mixgtk_widget_factory_get (top, MIXGTK_WIDGET_LOG);    g_return_val_if_fail (dis_data_.log != NULL, FALSE);    if (text)    {      gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, text, -1);      g_free (text);    }    if (!dis_data_.dispatcher)    {      static const gchar *HISTORY_FILE = "gmixvm.history";      static gint HISTORY_SIZE = 100;      mix_config_t *config = mixgtk_config_get_mix_config ();            int r = pipe (dis_data_.fildes);      g_return_val_if_fail (r == 0, FALSE);      /* connect stdout/stderr to the pipe's write end */      if (dup2 (dis_data_.fildes[1], STDOUT_FILENO) == -1	  || dup2 (dis_data_.fildes[1], STDERR_FILENO) == -1)	return FALSE;      dis_data_.out = fdopen (dis_data_.fildes[1], "w");      g_return_val_if_fail (dis_data_.out != NULL, FALSE);      r = fcntl (dis_data_.fildes[0], F_GETFL, 0);      g_return_val_if_fail (r != -1, FALSE);      r |= O_NONBLOCK;      r = fcntl(dis_data_.fildes[0], F_SETFL, r);      g_return_val_if_fail (r != -1, FALSE);      if (!mix_config_get_history_file (config))	mix_config_set_history_file (config, HISTORY_FILE);      if (mix_config_get_history_size (config) == 0)	mix_config_set_history_size (config, HISTORY_SIZE);      dis_data_.dispatcher =	mix_vm_cmd_dispatcher_new_with_config (dis_data_.out,					       dis_data_.out,					       config);      mix_vm_cmd_dispatcher_print_time (dis_data_.dispatcher, FALSE);            install_hooks_ ();    }    dis_data_.status =    mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_STATUSBAR);  g_return_val_if_fail (dis_data_.status != NULL, FALSE);  dis_data_.context = gtk_statusbar_get_context_id (GTK_STATUSBAR						    (dis_data_.status),						    "cmd_dis_context");  if (!restart) read_config_ ();  if (dis_data_.last_file)    gtk_window_set_title      (GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN)),       dis_data_.last_file);  restart = TRUE;  return TRUE;}/* dispatch an externally provided command */#ifdef MAKE_GUILEstatic gbooleantry_guile_ (const gchar *command){  if (command && command[0] == '(' && command[strlen (command) - 1] == ')')    {      mixguile_interpret_command (command);      return TRUE;    }  return FALSE;}#else#  define try_guile_(ignored)  FALSE#endifvoidmixgtk_cmd_dispatcher_dispatch (const gchar *command){  GtkWidget *entry = dis_data_.prompt;  g_return_if_fail (command != NULL);  g_assert (entry != NULL);  gtk_entry_set_text (GTK_ENTRY (entry), command);  log_command_ (&dis_data_, command);  if (!try_guile_ (command))    mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, command);  gtk_entry_set_text (GTK_ENTRY (entry), "");}/* get times */voidmixgtk_cmd_dispatcher_get_times (gint *uptime, gint *progtime, gint *laptime){  if (uptime != NULL)    *uptime = mix_vm_cmd_dispatcher_get_uptime (dis_data_.dispatcher);  if (progtime != NULL)    *progtime = mix_vm_cmd_dispatcher_get_progtime (dis_data_.dispatcher);  if (laptime != NULL)    *laptime = mix_vm_cmd_dispatcher_get_laptime (dis_data_.dispatcher);}/* get the underlying vm */mix_vm_t *mixgtk_cmd_dispatcher_get_vm (void){  return (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (dis_data_.dispatcher);}/* get the current source file */const gchar *mixgtk_cmd_dispatcher_get_src_path (void){  return mix_vm_cmd_dispatcher_get_src_file_path (dis_data_.dispatcher);}/* get the mix cmd dispatcher */mix_vm_cmd_dispatcher_t *mixgtk_cmd_dispatcher_get_mix_dispatcher (void){  return dis_data_.dispatcher;}/* process commands */voidcomplete_command_ (void){  GtkEntry *entry = GTK_ENTRY (dis_data_.prompt);  gchar *prefix = NULL;  gchar *text = gtk_entry_get_text (entry);  const GList  *cmds =    mix_vm_cmd_dispatcher_complete (dis_data_.dispatcher, text, &prefix);  if (prefix != NULL)    {      gtk_entry_set_text (entry, prefix);      g_free (prefix);      if (g_list_length ((GList *)cmds) > 1)	{	  static gchar BUFFER[25];	  gint k = 0;	  gtk_text_insert (GTK_TEXT (dis_data_.log),			   NULL, NULL, NULL, "Completions:\n", -1);	  while (cmds)	    {	      snprintf (BUFFER, 25, "%-12s", (const char*)cmds->data);	      ++k;	      gtk_text_insert (GTK_TEXT (dis_data_.log),			       NULL, NULL, NULL, BUFFER, -1);	      if (k%5 == 0)		gtk_text_insert (GTK_TEXT (dis_data_.log),				 NULL, NULL, NULL, "\n", -1);	      	      cmds = cmds->next;	    }	  if (k%5 != 0)	    gtk_text_insert (GTK_TEXT (dis_data_.log),			     NULL, NULL, NULL, "\n", -1);	}      else	gtk_entry_append_text (entry, " ");    }}inton_command_prompt_key_press_event (GtkEntry *w, GdkEventKey *e, gpointer d){  guint key = e->keyval;#ifdef HAVE_LIBHISTORY  HIST_ENTRY *entry = NULL;  if (key == GDK_Up)    {      entry = previous_history ();      if (entry && entry->line)	gtk_entry_set_text (w, entry->line);      return TRUE;    }  if (key == GDK_Down)    {      entry = next_history ();      if (entry && entry->line)	gtk_entry_set_text (w, entry->line);      return TRUE;    }#endif  if (key == GDK_Tab)    {      complete_command_ ();      return TRUE;    }  if (key == GDK_Return)    {      gchar *text = g_strstrip (gtk_entry_get_text (w));      if (text && *text)	{	  log_command_ (&dis_data_, text);	  if (!try_guile_ (text))	    mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text);	  gtk_entry_set_text (w, "");	}      return TRUE;    }    return FALSE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -