📄 mixgtk_device.c
字号:
/* -*-c-*- ---------------- mixgtk_device.c : * actual types for mixgtk devices * ------------------------------------------------------------------ * $Id: mixgtk_device.c,v 1.17 2002/03/29 16:30:49 jao Exp $ * ------------------------------------------------------------------ * Copyright (C) 2001, 2002 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <mixlib/mix_vm_command.h>#include <mixlib/xmix_device.h>#include "mixgtk.h"#include "mixgtk_gen_handlers.h"#include "mixgtk_widgets.h"#include "mixgtk_config.h"#include "mixgtk_cmd_dispatcher.h"#include "mixgtk_device.h"#define BIN_DEV_COL_ 5static const gchar *DEV_FORMAT_KEY_ = "Device.format";/* device container */static GtkNotebook *container_ = NULL;/* devdir dialog */static GtkWidget *devdir_dlg_ = NULL;static GtkEntry *devdir_entry_ = NULL;/** configuration stuff */#define LAST_BIN_DEV_ mix_dev_DISK_7static GtkWidget *devdlg_ = NULL;static GtkWidget *dtoggle_ = NULL;static GtkWidget *wtoggle_ = NULL;static GtkWidget *combo_ = NULL;static gint last_pos_ = 0;/* virtual machine */static mix_vm_t *vm_ = NULL;/* dec settings */static gint32 decs_ = 0;static gint32 new_decs_ = 0;/* macros manipulating dec settings */#define IS_DEC(flags,type) (((flags) >> (type)) & 1)#define SET_DEC(flags,type) ((flags) |= (1<<(type)))#define CLEAR_DEC(flags,type) ((flags) &= ~(1<<(type)))/* a mixgtk device */struct mixgtk_device_t{ mix_device_t device; GtkWidget *widget; gint pos;};struct mixgtk_bin_device_t{ struct mixgtk_device_t gtk_device; guint last_insert; GtkWidget *scroll; gboolean dec;};/* callbacks for output devices */static voidwrite_char_ (struct mixgtk_device_t *dev, const mix_word_t *block){ enum {MAX_BLOCK = 16, BUFF_SIZE = MAX_BLOCK * 5 + 2}; static gchar BUFFER[BUFF_SIZE]; guint k, j; for (k = 0; k < SIZES_[dev->device.type]; k++) for (j = 1; j < 6; j++) { mix_char_t ch = mix_word_get_byte (block[k], j); BUFFER[5 * k + j - 1] = mix_char_to_ascii (ch); } BUFFER[5 * k] = '\n'; BUFFER[5 * k + 1] = '\0'; gtk_text_insert (GTK_TEXT (dev->widget), NULL, NULL, NULL, BUFFER, -1); }static const gchar *get_word_string_ (mix_word_t w, gboolean dec){ enum {BUFF_SIZE = 17}; static gchar BUFFER[BUFF_SIZE] = { 0 }; if (dec) snprintf (BUFFER, BUFF_SIZE, "%s%011ld", mix_word_is_negative (w)? "-" : "+", mix_word_magnitude (w)); else mix_word_print_to_buffer (w, BUFFER); return BUFFER;}static voidwrite_bin_ (struct mixgtk_bin_device_t *dev, const mix_word_t *block){ static gchar *DEFTEXT[BIN_DEV_COL_] = { "0", "0", "0", "0", "0" }; guint k, col, row; gboolean dec = FALSE; GtkCList *list = GTK_CLIST (dev->gtk_device.widget); dec = IS_DEC(decs_, dev->gtk_device.device.type); gtk_clist_freeze (list); for (k = 0; k < SIZES_[dev->gtk_device.device.type]; k++) { row = dev->last_insert / BIN_DEV_COL_; col = dev->last_insert % BIN_DEV_COL_; if (col == 0) { int j; mix_word_t *words = g_new (mix_word_t, 5); gtk_clist_append (list, DEFTEXT); for (j = 0; j < 5; ++j) words[j] = block[k + j]; gtk_clist_set_row_data_full (list, row, (gpointer)words, g_free); } gtk_clist_set_text (list, row, col, get_word_string_ (block[k], dec)); dev->last_insert++; } gtk_clist_thaw (list);}static voidredraw_bin_device_ (struct mixgtk_bin_device_t *dev){ gint k, col, row; gboolean dec = FALSE; mix_word_t *words = NULL; GtkCList *list; if (!dev) return; list = GTK_CLIST (dev->gtk_device.widget); dec = IS_DEC(decs_, dev->gtk_device.device.type); gtk_clist_freeze (list); for (k = 0; k < dev->last_insert; ++k) { row = k / BIN_DEV_COL_; col = k % BIN_DEV_COL_; if (col == 0) words = gtk_clist_get_row_data (list, row); gtk_clist_set_text (list, row, col, get_word_string_ (words[col], dec)); } gtk_clist_thaw (list);} static gbooleanwrite_ (mix_device_t *dev, const mix_word_t *block){ struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *) dev; if (dev->type != mix_dev_CONSOLE && !(DEF_DEV_VTABLE_->write)(dev, block)) return FALSE; if (MODES_[dev->type] == mix_dev_CHAR) write_char_ (gtkdev, block); else write_bin_ ((struct mixgtk_bin_device_t *)gtkdev, block); gtk_notebook_set_page (container_, gtkdev->pos); return TRUE;}static gboolean read_ (mix_device_t *dev, mix_word_t *block){ struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *) dev; if (dev->type != mix_dev_CONSOLE && !(DEF_DEV_VTABLE_->read)(dev, block)) return FALSE; if (MODES_[dev->type] == mix_dev_CHAR) write_char_ (gtkdev, block); else write_bin_ ((struct mixgtk_bin_device_t *)gtkdev, block); gtk_notebook_set_page (container_, gtkdev->pos); return TRUE;}static gboolean ioc_ (mix_device_t *dev, mix_short_t cmd){ return (DEF_DEV_VTABLE_->ioc)(dev, cmd);}static gbooleanbusy_ (const mix_device_t *dev) { return (DEF_DEV_VTABLE_->busy)(dev);}static voiddestroy_ (mix_device_t *dev){ struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *)dev; if (MODES_[dev->type] == mix_dev_BIN) gtk_widget_destroy (((struct mixgtk_bin_device_t *)dev)->scroll); gtk_widget_destroy (gtkdev->widget); (DEF_DEV_VTABLE_->destroy) (dev); gtk_notebook_remove_page (GTK_NOTEBOOK (container_), gtkdev->pos); --last_pos_;}static mix_device_vtable_t MIXGTK_VTABLE_ = { write_, read_, ioc_, busy_, destroy_};/* create the gui part of the device */static voidmixgtk_device_construct_gui_ (struct mixgtk_device_t *dev){ GtkWidget *label = gtk_label_new (DEF_NAMES_[dev->device.type]); g_assert (label); dev->pos = last_pos_++; if (MODES_[dev->device.type] == mix_dev_CHAR) { GtkWidget *box = gtk_hbox_new (0, 0); GtkWidget *scroll = NULL; GtkAdjustment *vadj = NULL; dev->widget = gtk_text_new (NULL, NULL); g_assert (box); g_assert (dev->widget); gtk_text_set_editable (GTK_TEXT (dev->widget), FALSE); vadj = GTK_TEXT (dev->widget)->vadj; scroll = gtk_vscrollbar_new (vadj); gtk_box_pack_start (GTK_BOX (box), dev->widget, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box), scroll, FALSE, FALSE, 0); gtk_notebook_insert_page (container_, box, label, dev->pos); gtk_widget_show (box); gtk_widget_show (scroll); } else { gint k; struct mixgtk_bin_device_t *bindev = (struct mixgtk_bin_device_t *)dev; bindev->scroll = gtk_scrolled_window_new (NULL, NULL); g_assert (bindev->scroll); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bindev->scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); dev->widget = gtk_clist_new (BIN_DEV_COL_); g_assert (dev->widget); for (k =0; k < BIN_DEV_COL_; ++k) { gtk_clist_set_column_width (GTK_CLIST (dev->widget), k, 120); gtk_clist_set_column_auto_resize (GTK_CLIST (dev->widget), k, TRUE); } gtk_container_add (GTK_CONTAINER (bindev->scroll), dev->widget); gtk_notebook_insert_page (container_, bindev->scroll, label, dev->pos); gtk_widget_show (bindev->scroll); } gtk_widget_show (label); gtk_widget_set_style (dev->widget, gtk_widget_get_style (GTK_WIDGET (container_))); gtk_widget_show (dev->widget); gtk_widget_draw (GTK_WIDGET (container_), NULL);}/* create a new mixgtk device */static mix_device_t *mixgtk_device_new_ (mix_device_type_t type){ struct mixgtk_device_t *dev = NULL; g_return_val_if_fail (type < mix_dev_INVALID, NULL); if (MODES_[type] == mix_dev_CHAR) { dev = g_new (struct mixgtk_device_t, 1); } else { dev = (struct mixgtk_device_t *) g_new (struct mixgtk_bin_device_t, 1); ((struct mixgtk_bin_device_t *)dev)->last_insert = 0; } construct_device_ (&dev->device, type); dev->device.vtable = &MIXGTK_VTABLE_; mixgtk_device_construct_gui_ (dev); return (mix_device_t *)dev;}static mix_device_t *mixgtk_device_copy_ (const struct mixgtk_device_t *from){ struct mixgtk_device_t *result = (struct mixgtk_device_t *)mixgtk_device_new_ (from->device.type); g_return_val_if_fail (result != NULL, NULL); if (MODES_[from->device.type] == mix_dev_CHAR) { gchar *text = gtk_editable_get_chars (GTK_EDITABLE (from->widget), 0, -1); gtk_text_insert (GTK_TEXT (result->widget), NULL, NULL, NULL, text, -1); g_free (text); } else { static gchar *VALS[BIN_DEV_COL_] = {""}; struct mixgtk_bin_device_t *to = (struct mixgtk_bin_device_t *) result; struct mixgtk_bin_device_t *fr = (struct mixgtk_bin_device_t *) from; to->last_insert = fr->last_insert; to->dec = fr->dec; if (to->last_insert > 0) { gint k, j, rows = to->last_insert / BIN_DEV_COL_; GtkCList *tl = GTK_CLIST (result->widget); GtkCList *fl = GTK_CLIST (from->widget); for (k = 0; k < rows; ++k) { mix_word_t *words = g_new (mix_word_t, BIN_DEV_COL_); mix_word_t *oldwords = (mix_word_t *) gtk_clist_get_row_data (fl, k); for (j = 0; j < BIN_DEV_COL_; ++j) words[j] = oldwords[j]; gtk_clist_append (tl, VALS); gtk_clist_set_row_data_full (tl, k, words, g_free); } redraw_bin_device_ (to); } } return (mix_device_t *)result;}/* init default devices */gbooleanmixgtk_device_init (GtkNotebook *container, mix_vm_t *vm){ gint k = 0; g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (vm != NULL, FALSE); container_ = container; vm_ = vm; last_pos_ = 0; devdlg_ = NULL; devdir_dlg_ = NULL; devdir_entry_ = NULL; dtoggle_ = NULL; wtoggle_ = NULL; combo_ = NULL; /* remove dummy page from container */ gtk_notebook_remove_page (container_, 0); mix_vm_set_device_factory (vm, mixgtk_device_new_); /* read format configuration */ if (mixgtk_config_get (DEV_FORMAT_KEY_)) decs_ = atoi (mixgtk_config_get (DEV_FORMAT_KEY_)); /* re-create existing devices */ for (k = 0; k < mix_dev_INVALID; ++k) { mix_device_t *dev = mix_vm_get_device (vm, k); if (dev != NULL) { mix_device_t *newdev = mixgtk_device_copy_ ((struct mixgtk_device_t *)dev); mix_vm_connect_device (vm, newdev); } } /* set to first page */ gtk_notebook_set_page (container_, 0); return TRUE;}voidmixgtk_device_set_format (mix_device_type_t dev, gboolean dec){ gboolean changed; g_return_if_fail (dev < mix_dev_INVALID); changed = (dec && !IS_DEC (decs_, dev)) || (!dec && IS_DEC (decs_, dev)); if (changed && (MODES_[dev] == mix_dev_BIN)) { if (dec) SET_DEC (decs_, dev); else CLEAR_DEC (decs_, dev); redraw_bin_device_ ((struct mixgtk_bin_device_t *) mix_vm_get_device (vm_, dev)); } }static mix_device_type_tget_device_idx_ (void){ const gchar *name = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (combo_)->entry)); /* inefficient, but the list is short */ int k; for (k = 0; k <= LAST_BIN_DEV_; ++k) if (!strcmp (name, DEF_NAMES_[k])) return k; g_assert_not_reached (); return 0;}static voidinit_devform_ (void){ GList *names = NULL; int k; devdlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_DEVFORM_DIALOG); g_assert (devdlg_); dtoggle_ = mixgtk_widget_factory_get_child_by_name (MIXGTK_DEVFORM_DIALOG, "decradio"); g_assert (dtoggle_); wtoggle_ = mixgtk_widget_factory_get_child_by_name (MIXGTK_DEVFORM_DIALOG, "wordradio"); g_assert (wtoggle_); combo_ = mixgtk_widget_factory_get_child_by_name (MIXGTK_DEVFORM_DIALOG, "dev_combo"); g_assert (combo_); for (k = 0; k <= LAST_BIN_DEV_; ++k) names = g_list_append (names, (gchar *)DEF_NAMES_[k]); gtk_combo_set_popdown_strings (GTK_COMBO (combo_), names);}voidon_deventry_changed (){ mix_device_type_t dev = get_device_idx_ (); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtoggle_), IS_DEC (new_decs_, dev)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle_), !IS_DEC (new_decs_, dev));}voidon_devform_activate (){ if (!devdlg_) init_devform_ (); new_decs_ = decs_; gtk_widget_show (devdlg_); on_deventry_changed ();}voidon_decradio_toggled (GtkToggleButton *button){ if (gtk_toggle_button_get_active (button)) SET_DEC (new_decs_, get_device_idx_ ()); else CLEAR_DEC (new_decs_, get_device_idx_ ());}voidon_devapp_button_clicked (){ int k; gchar value[20]; for (k = 0; k <= LAST_BIN_DEV_; ++k) mixgtk_device_set_format (k, IS_DEC (new_decs_, k)); decs_ = new_decs_; snprintf (value, 20, "%d", decs_); mixgtk_config_update (DEV_FORMAT_KEY_, value);}voidon_devok_button_clicked (){ on_devapp_button_clicked (); gtk_widget_hide (devdlg_);}voidon_devcancel_button_clicked (){ gtk_widget_hide (devdlg_);}voidon_devset_button_clicked (){ static gint32 ON = 0xffff, OFF = 0; new_decs_ = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dtoggle_)))? ON : OFF;}voidon_devdir_activate (){ static const gchar *DEVDIR_ENTRY_NAME = "devdir_entry"; if (devdir_dlg_ == NULL) { devdir_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_DEVDIR_DIALOG); g_assert (devdir_dlg_); devdir_entry_ = GTK_ENTRY (mixgtk_widget_factory_get_child_by_name (MIXGTK_DEVDIR_DIALOG, DEVDIR_ENTRY_NAME)); g_assert (devdir_entry_); } gtk_entry_set_text (devdir_entry_, mix_device_get_dir ()); gtk_widget_show (devdir_dlg_);}static voiddevdir_callback (const gchar *file){ gtk_entry_set_text (devdir_entry_, file);}voidon_devdir_browse_clicked (){ mixgtk_get_file (devdir_callback, "Devices dir", mix_device_get_dir ());}voidon_devdir_cancel_clicked (){ gtk_widget_hide (devdir_dlg_);}voidon_devdir_ok_clicked (){ const gchar *dirname = gtk_entry_get_text (devdir_entry_); gchar *cmd = g_strconcat (mix_vm_command_to_string (MIX_CMD_SDDIR), " ", dirname, NULL); gtk_widget_hide (devdir_dlg_); mixgtk_cmd_dispatcher_dispatch (cmd); g_free (cmd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -