#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <X11/Xlib.h>
#include <errno.h>
#include <pthread.h>


#include "callbacks.h"
#include "interface.h"
#include "support.h"
#include "vncviewer.h"

void makeTable_dialog_viewset(int pCnt);
void makeList_dialog_viewset(int pCnt);
void expanding_screen(void);
GtkWidget *create_rightclickmenu1 (gpointer user_data);
GtkWidget *create_rightclickmenu2 (gpointer user_data);
GtkWidget *makeTable_userList(void);
GtkWidget *makeTable_send_state(void);
void makeCombobox1_dialog_send(void);
void makeCombobox2_dialog_send(void);
void send_start(void);
void locking_start(void);

gint keyindex;
extern Display *dpy;
extern gboolean modifierPressed[16];
extern GtkWidget *table[];
extern GtkWidget *namelabel[][ROW_MAX * COLUMN_MAX];

int tab_num_tmp;
int dialog_viewset_page, dialog_viewset_area;
int dialog_viewset_clientnum[TAB_MAX][TABGROUP_MAX];
GtkWidget *dialog_viewset;
GtkWidget *dialog_viewset_table;
GtkWidget *dialog_viewset_entry[TAB_MAX];
GtkWidget *dialog_viewset_spinbutton_row[TAB_MAX];
GtkWidget *dialog_viewset_spinbutton_col[TAB_MAX];
GtkWidget *dialog_viewset_listviewport[TAB_MAX];
GtkWidget *dialog_viewset_list[TAB_MAX];
extern GtkWidget *dialog_viewset_viewport;
extern IMAGEINFO *iinfo_ex;

GtkWidget *window_ex;
extern int exwindowWidth, exwindowHeight;
GtkWidget *drawingarea_ex;

GtkWidget *dialog_send;
int maxcastnum = 0;
GtkWidget *src_checkbutton;
gboolean recv_state_tmp[MAXCLIENT];
gboolean send_state_tmp[MAXCLIENT];
GtkWidget *dialog_send_checkbutton1[TAB_MAX];
GtkWidget *dialog_send_checkbutton2[TAB_MAX][TABGROUP_MAX];
GtkWidget *dialog_send_checkbutton4[MAXCLIENT];
GtkWidget *dialog_send_table1;
GtkWidget *dialog_send_table2;
GtkWidget *dialog_send_label_ID;
GtkWidget *dialog_send_comboboxentry1;
GtkWidget *dialog_send_comboboxentry2;
char fullscreen_flag;

extern GtkWidget *dialog_IDinput;
char server_name[IDLENGTH];

GtkWidget *dialog_lock;
GtkWidget *dialog_lock_table;

#if 0
GtkWidget *dialog_record;
GtkWidget *dialog_record_table;
int recording (int rec_time, int fps, char *geometry);
#endif

GtkWidget *dialog_quit;

GtkWidget *dialog_version;

GtkWidget *dialog_notice;

extern void *AcceptLoop (void *arg);
extern int SendRecvLoop (int acc, int fsize, char *fname);


/*******************************************************************
 *メインウィンドウに対するイベントのコールバック関数
 *******************************************************************/

gboolean
on_main_window_delete_event                (GtkWidget       *widget,
					    GdkEvent        *event,
					    gpointer         user_data)
{
  dialog_quit = create_dialog_quit();
  gtk_widget_show(dialog_quit);
  gtk_grab_add(dialog_quit);

  return TRUE;
}


void
on_notebook_switch_page                (GtkNotebook     *notebook,
					GtkNotebookPage *page,
					guint            page_num,
					gpointer         user_data)
{
  int dCnt, c_num;

  /* Cut VNCconnection (hide page) */
  for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
    if ((c_num = draw_info[current_page].client_num[dCnt]) == EMPTY) continue;
    if (GETSEND(c_num) || (GETVIEW(c_num))) continue;
    CutVNC(c_num);
    SendVncMsg(c_num);
  }

  /* Connect VNC (expose page) */
  current_page = page_num;
  for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
    if ((c_num = draw_info[current_page].client_num[dCnt]) == EMPTY) continue;
    if (server_CB.client_grp[c_num] == NULL) continue;
    SendAllowMsg(c_num, (char *)server_CB.client_grp[c_num]->client_ID);
  }
}


/*
  on_main_drawingarea_configure_event()は以下のイベントが起こった際に
  呼び出される.
    1. ウィンドウ作成直後
    2. ウィンドウのサイズを変更した時
*/
gboolean
on_main_drawingarea_configure_event        (GtkWidget       *widget,
					    GdkEventConfigure *event,
					    gpointer         user_data)
{
  page = ((int)user_data & 0xff00) >> 8;
  da_num = (int)user_data & 0x00ff;

  if (gdkpixmap[page][da_num])
    gdk_pixmap_unref(gdkpixmap[page][da_num]);

  gdkpixmap[page][da_num] = gdk_pixmap_new(widget->window,
			        widget->allocation.width,
			        widget->allocation.height, -1);

  gdk_draw_rectangle(gdkpixmap[page][da_num], widget->style->white_gc, TRUE,
		     0, 0, widget->allocation.width, widget->allocation.height);

  clientNum = draw_info[page].client_num[da_num];
  if (clientNum != EMPTY) {
    CreateImageInfo(FALSE);
    draw_image(gdkpixmap[page][da_num], gdkGC, gdkimage[clientNum], 0, 0, 0, 0,
               gdkimage[clientNum]->width, gdkimage[clientNum]->height);
  }

  return TRUE;
}


/*
  on_main_drawingarea_expose_event()は以下のイベントが起こった際に
  呼び出される.
    1. 最小化されていたウィンドウが再び表示された時
    2. 他のウィンドウによって隠れていた領域が再び現れた時
*/
gboolean
on_main_drawingarea_expose_event           (GtkWidget       *widget,
					    GdkEventExpose  *event,
					    gpointer         user_data)
{
  page = ((int)user_data & 0xff00) >> 8;
  da_num = (int)user_data & 0x00ff;

  gdk_draw_pixmap(widget->window,
		  widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
		  gdkpixmap[page][da_num],
		  event->area.x, event->area.y,
		  event->area.x, event->area.y,
		  event->area.width, event->area.height);
  
  return FALSE;
}


gboolean
on_main_drawingarea_button_press_event     (GtkWidget       *widget,
					    GdkEventButton  *event,
					    gpointer         user_data)
{
  GtkWidget *menu;

  page = ((int)user_data & 0xff00) >> 8;
  da_num = (int)user_data & 0x00ff;
  clientNum = draw_info[page].client_num[da_num];

  if (clientNum == EMPTY) return TRUE;
  /* drawing area内でマウスの右ボタンが押下された時の処理 */
  if (event->button == 3) {
    menu = create_rightclickmenu1(user_data);
    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
		   event->button, event->time);
  } else {
    /* drawing area内でダブルクリックされた時の処理 */
    if (event->type == GDK_2BUTTON_PRESS) {
      SETCTRL(clientNum, FALSE);
      expanding_screen();
      GtkWidget *window_ex_togglebutton = lookup_widget(GTK_WIDGET(window_ex), "window_ex_togglebutton");
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(window_ex_togglebutton), FALSE);
    }
  }

  return TRUE;
}


gboolean
on_main_drawingarea_button_release_event   (GtkWidget       *widget,
					    GdkEventButton  *event,
					    gpointer         user_data)
{
  return FALSE;
}


gboolean
on_main_drawingarea_motion_notify_event    (GtkWidget       *widget,
					    GdkEventMotion  *event,
					    gpointer         user_data)
{
  return FALSE;
}


/*******************************************************************
 *メインウィンドウのメニュー
 *******************************************************************/
void
on_network_activate                    (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_save_activate                       (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_quit_activate                    (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  dialog_quit = create_dialog_quit();
  gtk_widget_show(dialog_quit);
  gtk_grab_add(dialog_quit);
}


void
on_viewset_activate                    (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  int pCnt, dCnt;

  tab_num_tmp = tab_num;
  for (pCnt = 0; pCnt < tab_num; pCnt++) 
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) 
      dialog_viewset_clientnum[pCnt][dCnt] = EMPTY;

  dialog_viewset = create_dialog_viewset();
  GtkWidget *dialog_viewset_viewport = lookup_widget(GTK_WIDGET(dialog_viewset), "dialog_viewset_viewport");
  dialog_viewset_table = gtk_table_new (2*tab_num-1, tab_num, FALSE);
  gtk_widget_show (dialog_viewset_table);
  gtk_container_add (GTK_CONTAINER (dialog_viewset_viewport), dialog_viewset_table);
  for (pCnt = 0; pCnt < tab_num; pCnt++)
    makeTable_dialog_viewset(pCnt);

  gtk_widget_show(dialog_viewset);
  gtk_grab_add(dialog_viewset);
}


void
on_send_activate                       (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  int Cnt, pCnt, dCnt;
  int user_cnt = 0;

  src_checkbutton = NULL;
  for (Cnt = 0; Cnt < MAXCLIENT; Cnt++) {
    if (server_CB.client_grp[Cnt] == NULL) continue;
    recv_state_tmp[Cnt] = GETRECV(Cnt);
    send_state_tmp[Cnt] = GETSEND(Cnt);
    if (server_CB.user_num == ++user_cnt) break;
  }
  fullscreen_flag = 0;	// デフォルト画面送信を通常ウィンドウ

  dialog_send = create_dialog_send();

  makeCombobox1_dialog_send();
  makeCombobox2_dialog_send();

  dialog_send_table1 = makeTable_userList();
  for (pCnt = 0; pCnt < tab_num; pCnt++) {
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if (draw_info[pCnt].client_num[dCnt] == EMPTY) continue;
      if (GETRECV(draw_info[pCnt].client_num[dCnt]) || \
	  (strcmp((char *)server_CB.client_grp[draw_info[pCnt].client_num[dCnt]]->client_ID, \
	  (char *)server_CB.server_ID) == 0))
	gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dialog_send_checkbutton2[pCnt][dCnt]), TRUE);
      else
	g_signal_connect ((gpointer) dialog_send_checkbutton2[pCnt][dCnt], "toggled",
			  G_CALLBACK (on_dialog_send_checkbutton2_toggled),
			  (gpointer) ((pCnt << 8)+dCnt));
    }
    g_signal_connect ((gpointer) dialog_send_checkbutton1[pCnt], "toggled",
		      G_CALLBACK (on_dialog_send_checkbutton1_toggled),
		      (gpointer) pCnt);
  }

  GtkWidget *dialog_send_viewport1 = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_viewport1");
  GtkWidget *dialog_send_viewport2 = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_viewport2");
  gtk_container_add (GTK_CONTAINER (dialog_send_viewport1), dialog_send_table1);
  gtk_widget_show (dialog_send_table1);

  dialog_send_table2 = makeTable_send_state();
  gtk_container_add (GTK_CONTAINER (dialog_send_viewport2), dialog_send_table2);
  gtk_widget_show (dialog_send_table2);

  gtk_widget_show(dialog_send);
  gtk_grab_add(dialog_send);
}


void
on_lock_activate                       (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  int pCnt, dCnt;

  dialog_lock = create_dialog_lock();
  dialog_lock_table = makeTable_userList();
  for (pCnt = 0; pCnt < tab_num; pCnt++) {
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if (draw_info[pCnt].client_num[dCnt] == EMPTY) continue;
      if (strcmp((char *)server_CB.client_grp[draw_info[pCnt].client_num[dCnt]]->client_ID, \
	  (char *)server_CB.server_ID) == 0) {
	gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dialog_send_checkbutton2[pCnt][dCnt]), TRUE);
      } else {
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[pCnt][dCnt]), \
	    			     GETLOCK(draw_info[pCnt].client_num[dCnt]));
        g_signal_connect ((gpointer) dialog_send_checkbutton2[pCnt][dCnt], "toggled",
			  G_CALLBACK (on_dialog_lock_checkbutton2_toggled),
			  (gpointer) ((pCnt << 8)+dCnt));
      }
    }
    g_signal_connect ((gpointer) dialog_send_checkbutton1[pCnt], "toggled",
		      G_CALLBACK (on_dialog_lock_checkbutton1_toggled),
		      (gpointer) pCnt);
  }
  GtkWidget *dialog_lock_viewport = lookup_widget(GTK_WIDGET(dialog_lock), "dialog_lock_viewport");
  gtk_container_add (GTK_CONTAINER (dialog_lock_viewport), dialog_lock_table);
  gtk_widget_show (dialog_lock_table);

  gtk_widget_show(dialog_lock);
  gtk_grab_add(dialog_lock);
}


void
on_version_activate                    (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  dialog_version = create_dialog_version();
  gtk_widget_show(dialog_version);
  gtk_grab_add(dialog_version);
}


/*******************************************************************
 *ID入力ダイアログで使用する関数
 *******************************************************************/

gboolean
on_dialog_IDinput_delete_event         (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  return TRUE;
}


void
on_dialog_IDinput_entry_changed       (GtkEditable     *editable,
                                        gpointer         user_data)
{
  strcpy(server_name, (char *)gtk_entry_get_text(GTK_ENTRY(editable)));
}


void
on_dialog_IDinput_buttonOK_clicked     (GtkButton       *button,
                                        gpointer         user_data)
{
  //printf("ID Length: %d\n", strlen(server_name));
  if (strlen(server_name) < 1) return -1;
//  strcpy((char *)server_CB.server_ID, server_name);
  memcpy((char *)server_CB.server_ID, server_name, IDLENGTH);
  gtk_grab_remove(dialog_IDinput);
  gtk_widget_destroy(dialog_IDinput);
  return gtk_main_quit();
}


void
on_dialog_IDinput_buttonCancel_clicked (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_IDinput);
  gtk_widget_destroy(dialog_IDinput);
  Cleanup();
  exit(0);
}


/*******************************************************************
 *表示設定で使用する関数
 *******************************************************************/

/*
  表示設定ダイアログ内のtableウィジェットの作成
 */ 
void makeTable_dialog_viewset(int pCnt)
{
  int Cnt, user_cnt;
  char labelname[16];
  GtkWidget *hseparator[TAB_MAX-1];
  GtkWidget *labelTab[TAB_MAX];
  GtkWidget *vbox[TAB_MAX];
  GtkWidget *hbox_row[TAB_MAX];
  GtkWidget *label_row[TAB_MAX];
  GtkObject *spinbutton_adj_row[TAB_MAX];
  GtkWidget *hbox_col[TAB_MAX];
  GtkWidget *label_col[TAB_MAX];
  GtkObject *spinbutton_adj_col[TAB_MAX];
  GtkWidget *scrolledwindow[TAB_MAX];

  /* セパレータの作成 */
  if (pCnt != 0) {
    hseparator[pCnt-1] = gtk_hseparator_new ();
    gtk_widget_show (hseparator[pCnt-1]);
    gtk_table_attach (GTK_TABLE (dialog_viewset_table), hseparator[pCnt-1], 0, 3, 2*pCnt-1, 2*pCnt,
		      (GtkAttachOptions) (GTK_FILL),
		      (GtkAttachOptions) (GTK_FILL), 0, 0);
  }

  /* label "tab x" */
  sprintf(labelname, _("tab %d"), pCnt+1);
  labelTab[pCnt] = gtk_label_new (_(labelname));
  gtk_widget_show (labelTab[pCnt]);
  gtk_table_attach (GTK_TABLE (dialog_viewset_table), labelTab[pCnt], 0, 1, 2*pCnt, 2*pCnt+1,
		    (GtkAttachOptions) (GTK_FILL),
		    (GtkAttachOptions) (0), 0, 0);
  gtk_misc_set_alignment (GTK_MISC (labelTab[pCnt]), 0, 0.5);
  gtk_widget_set_size_request (labelTab[pCnt], 50, -1);

  vbox[pCnt] = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox[pCnt]);
  gtk_table_attach (GTK_TABLE (dialog_viewset_table), vbox[pCnt], 1, 2, 2*pCnt, 2*pCnt+1,
		    (GtkAttachOptions) (GTK_FILL),
		    (GtkAttachOptions) (GTK_FILL), 0, 0);

  /* グループ名を入力するためのtext entryの作成 */
  dialog_viewset_entry[pCnt] = gtk_entry_new ();
  gtk_widget_show (dialog_viewset_entry[pCnt]);
  gtk_box_pack_start (GTK_BOX (vbox[pCnt]), dialog_viewset_entry[pCnt], FALSE, FALSE, 0);
  gtk_entry_set_text (GTK_ENTRY (dialog_viewset_entry[pCnt]), _(draw_info[pCnt].group_name));
  gtk_entry_set_max_length (GTK_ENTRY (dialog_viewset_entry[pCnt]), 8);

  hbox_row[pCnt] = gtk_hbox_new (FALSE, 0);
  gtk_widget_show (hbox_row[pCnt]);
  gtk_box_pack_start (GTK_BOX (vbox[pCnt]), hbox_row[pCnt], TRUE, TRUE, 0);

  /* label "row" */
  label_row[pCnt] = gtk_label_new (_("row"));
  gtk_widget_show (label_row[pCnt]);
  gtk_box_pack_start (GTK_BOX (hbox_row[pCnt]), label_row[pCnt], FALSE, FALSE, 0);

  /* spin buttonの作成 */
  spinbutton_adj_row[pCnt] = gtk_adjustment_new (draw_info[pCnt].row, 1, 4, 1, 1, 1);
  dialog_viewset_spinbutton_row[pCnt] = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj_row[pCnt]), 1, 0);
  gtk_widget_show (dialog_viewset_spinbutton_row[pCnt]);
  gtk_box_pack_start (GTK_BOX (hbox_row[pCnt]), dialog_viewset_spinbutton_row[pCnt], TRUE, TRUE, 0);

  hbox_col[pCnt] = gtk_hbox_new (FALSE, 0);
  gtk_widget_show (hbox_col[pCnt]);
  gtk_box_pack_start (GTK_BOX (vbox[pCnt]), hbox_col[pCnt], TRUE, TRUE, 0);

  /* label "column" */
  label_col[pCnt] = gtk_label_new (_("column"));
  gtk_widget_show (label_col[pCnt]);
  gtk_box_pack_start (GTK_BOX (hbox_col[pCnt]), label_col[pCnt], FALSE, FALSE, 0);

  /* spin buttonの作成 */
  spinbutton_adj_col[pCnt] = gtk_adjustment_new (draw_info[pCnt].column, 1, 4, 1, 1, 1);
  dialog_viewset_spinbutton_col[pCnt] = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj_col[pCnt]), 1, 0);
  gtk_widget_show (dialog_viewset_spinbutton_col[pCnt]);
  gtk_box_pack_start (GTK_BOX (hbox_col[pCnt]), dialog_viewset_spinbutton_col[pCnt], TRUE, TRUE, 0);

  scrolledwindow[pCnt] = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (scrolledwindow[pCnt]);
  gtk_table_attach (GTK_TABLE (dialog_viewset_table), scrolledwindow[pCnt], 2, 3, 2*pCnt, 2*pCnt+1,
		    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
		    (GtkAttachOptions) (GTK_FILL), 0, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow[pCnt]), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);

  dialog_viewset_listviewport[pCnt] = gtk_viewport_new(NULL, NULL);
  gtk_widget_show(dialog_viewset_listviewport[pCnt]);
  gtk_container_add (GTK_CONTAINER (scrolledwindow[pCnt]), dialog_viewset_listviewport[pCnt]);

  user_cnt = 0;
  for (Cnt = 0; Cnt < TABGROUP_MAX; Cnt++) {
    if (draw_info[pCnt].client_num[Cnt] == EMPTY) continue;
    dialog_viewset_clientnum[pCnt][user_cnt] = draw_info[pCnt].client_num[Cnt];
    user_cnt++;
  }
  for (Cnt = user_cnt; Cnt < TABGROUP_MAX; Cnt++) {
    dialog_viewset_clientnum[pCnt][Cnt] = EMPTY;
  }

  makeList_dialog_viewset(pCnt);
}

/*
  表示設定ダイアログ内のListウィジェットの作成
 */
void makeList_dialog_viewset(int pCnt)
{
  int dCnt;
  GtkWidget *item;

  dialog_viewset_list[pCnt] = gtk_list_new ();
  for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
    if (dialog_viewset_clientnum[pCnt][dCnt] == EMPTY) continue;
    item = gtk_list_item_new_with_label((gchar *)server_CB.client_grp[dialog_viewset_clientnum[pCnt][dCnt]]->client_ID);
    gtk_container_add(GTK_CONTAINER(dialog_viewset_list[pCnt]), item);
    gtk_widget_show(item);
  }
  gtk_container_add(GTK_CONTAINER(dialog_viewset_listviewport[pCnt]), dialog_viewset_list[pCnt]);
  gtk_widget_show (dialog_viewset_list[pCnt]);
  gtk_list_set_selection_mode (GTK_LIST (dialog_viewset_list[pCnt]), GTK_SELECTION_SINGLE);

  g_signal_connect ((gpointer) dialog_viewset_list[pCnt], "select_child",
		    G_CALLBACK (on_dialog_viewset_list_select_child),
		    (gpointer) pCnt);
}


gboolean
on_dialog_viewset_delete_event                (GtkWidget       *widget,
					       GdkEvent        *event,
					       gpointer         user_data)
{
  gtk_grab_remove(dialog_viewset);
  gtk_widget_destroy(dialog_viewset);
  dialog_viewset = NULL;

  return TRUE;
}


void
on_dialog_viewset_buttonOK_clicked             (GtkButton       *button,
						gpointer         user_data)
{
  int pCnt, dCnt, num;
  int oldareamax, newareamax;

  tab_num = tab_num_tmp;
  for (pCnt = 0; pCnt < tab_num; pCnt++) {
    strcpy(draw_info[pCnt].group_name, gtk_editable_get_chars(GTK_EDITABLE(dialog_viewset_entry[pCnt]), 0, -1));

    oldareamax = draw_info[pCnt].row * draw_info[pCnt].column;
    draw_info[pCnt].row = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog_viewset_spinbutton_row[pCnt]));
    draw_info[pCnt].column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog_viewset_spinbutton_col[pCnt]));
    newareamax = draw_info[pCnt].row * draw_info[pCnt].column;
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if (dCnt < oldareamax) {
	if (table[pCnt] != NULL) {
          gtk_container_remove(GTK_CONTAINER(table[pCnt]), namelabel[pCnt][dCnt]);
          gtk_container_remove(GTK_CONTAINER(table[pCnt]), drawingarea[pCnt][dCnt]);
	}
      }
      num = dialog_viewset_clientnum[pCnt][dCnt];
      draw_info[pCnt].client_num[dCnt] = num;
      if (num == EMPTY) continue;
      server_CB.client_grp[num]->draw_page = pCnt;
      server_CB.client_grp[num]->draw_area = dCnt;
      if (((dCnt < newareamax) && (pCnt == current_page)) || (GETVIEW(num) || (GETSEND(num)))) {
	/* Connect VNC */
	SendAllowMsg(num, (char *)server_CB.client_grp[num]->client_ID);
      } else {
	/* Cut VNCconnection */
	CutVNC(num);
	SendVncMsg(num);
      }
    }

    makeTable(pCnt, draw_info[pCnt].row, draw_info[pCnt].column);
  }
  gtk_grab_remove(dialog_viewset);
  gtk_widget_destroy(dialog_viewset);
  dialog_viewset = NULL;
}


void
on_dialog_viewset_buttonCancel_clicked             (GtkButton       *button,
					       gpointer         user_data)
{
  gtk_grab_remove(dialog_viewset);
  gtk_widget_destroy(dialog_viewset);
  dialog_viewset = NULL;
}


/*
  「タブの追加」ボタンがクリックされた際に呼び出される.
 */
void
on_dialog_viewset_button_tab_clicked          (GtkButton       *button,
					       gpointer         user_data)
{
  char g_name[16];

  if (tab_num_tmp == TAB_MAX) return;
  sprintf(g_name, "group%d", tab_num_tmp+1);
  strcpy(draw_info[tab_num_tmp].group_name, g_name);
  draw_info[tab_num_tmp].row = 2;
  draw_info[tab_num_tmp].column = 2;
  makeTable_dialog_viewset(tab_num_tmp);
  tab_num_tmp++;
}


/*
  「上のグループに移動」ボタンがクリックされた際に呼び出される.
 */
void
on_dialog_viewset_button_moveupg_clicked      (GtkButton       *button,
					       gpointer         user_data)
{
  int bottom = 0, dCnt = dialog_viewset_area;

  if (dialog_viewset_page == 0) return;
  while (dialog_viewset_clientnum[dialog_viewset_page - 1][bottom] != EMPTY)
    bottom++;
  dialog_viewset_clientnum[dialog_viewset_page - 1][bottom] = dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area];

  while (dialog_viewset_clientnum[dialog_viewset_page][dCnt] != EMPTY) {
    dialog_viewset_clientnum[dialog_viewset_page][dCnt] = dialog_viewset_clientnum[dialog_viewset_page][dCnt + 1];
    dCnt++;
  }
  gtk_container_remove(GTK_CONTAINER(dialog_viewset_listviewport[dialog_viewset_page]), dialog_viewset_list[dialog_viewset_page]);
  makeList_dialog_viewset(dialog_viewset_page);

  dialog_viewset_page--;
  dialog_viewset_area = bottom;
  gtk_container_remove(GTK_CONTAINER(dialog_viewset_listviewport[dialog_viewset_page]), dialog_viewset_list[dialog_viewset_page]);
  makeList_dialog_viewset(dialog_viewset_page);
}


/*
  「上に移動」ボタンがクリックされた際に呼び出される.
 */
void
on_dialog_viewset_button_moveup_clicked       (GtkButton       *button,
					       gpointer         user_data)
{
  int tmp;

  if (dialog_viewset_area == 0) return;
  tmp = dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area];
  dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area] = dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area - 1];
  dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area - 1] = tmp;
  dialog_viewset_area--;

  gtk_container_remove(GTK_CONTAINER(dialog_viewset_listviewport[dialog_viewset_page]), dialog_viewset_list[dialog_viewset_page]);
  makeList_dialog_viewset(dialog_viewset_page);
}


/*
  「下に移動」ボタンがクリックされた際に呼び出される.
 */
void
on_dialog_viewset_button_movedown_clicked     (GtkButton       *button,
					       gpointer         user_data)
{
  int tmp;

  if (dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area + 1] == EMPTY) return;
  tmp = dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area];
  dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area] = dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area + 1];
  dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area + 1] = tmp;
  dialog_viewset_area++;

  gtk_container_remove(GTK_CONTAINER(dialog_viewset_listviewport[dialog_viewset_page]), dialog_viewset_list[dialog_viewset_page]);
  makeList_dialog_viewset(dialog_viewset_page);
}


/*
  「下のグループに移動」ボタンがクリックされた際に呼び出される.
 */
void
on_dialog_viewset_button_movedowng_clicked    (GtkButton       *button,
					       gpointer         user_data)
{
  int bottom = 0, dCnt = dialog_viewset_area;

  if (dialog_viewset_page == tab_num_tmp - 1) return;
  while (dialog_viewset_clientnum[dialog_viewset_page + 1][bottom] != EMPTY)
    bottom++;
  dialog_viewset_clientnum[dialog_viewset_page + 1][bottom] = dialog_viewset_clientnum[dialog_viewset_page][dialog_viewset_area];

  while (dialog_viewset_clientnum[dialog_viewset_page][dCnt] != EMPTY) {
    dialog_viewset_clientnum[dialog_viewset_page][dCnt] = dialog_viewset_clientnum[dialog_viewset_page][dCnt + 1];
    dCnt++;
  }
  gtk_container_remove(GTK_CONTAINER(dialog_viewset_listviewport[dialog_viewset_page]), dialog_viewset_list[dialog_viewset_page]);
  makeList_dialog_viewset(dialog_viewset_page);

  dialog_viewset_page++;
  dialog_viewset_area = bottom;
  gtk_container_remove(GTK_CONTAINER(dialog_viewset_listviewport[dialog_viewset_page]), dialog_viewset_list[dialog_viewset_page]);
  makeList_dialog_viewset(dialog_viewset_page);
}


/*
  Listのアイテムが選択された際に呼び出される.
 */
void
on_dialog_viewset_list_select_child           (GtkList         *list,
					       GtkWidget       *widget,
					       gpointer         user_data)
{
  dialog_viewset_page = (int)user_data;
  dialog_viewset_area = gtk_list_child_position(list, widget);
}


void
add_to_dialog_viewset(int cnum)
{
  int pCnt, dCnt, flag = 0;
  GtkWidget *item;

  if (dialog_viewset == NULL) return;
  for (pCnt = 0; pCnt < tab_num_tmp; pCnt++) {
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if (dialog_viewset_clientnum[pCnt][dCnt] == cnum) return;
      if (dialog_viewset_clientnum[pCnt][dCnt] == EMPTY) {
	dialog_viewset_clientnum[pCnt][dCnt] = cnum;
	item = gtk_list_item_new_with_label((char *)server_CB.client_grp[cnum]->client_ID);
	gtk_container_add(GTK_CONTAINER(dialog_viewset_list[pCnt]), item);
	gtk_widget_show(item);
	flag = 1;
	return;
      }
    }
  }
  if (!flag)
    fprintf(stderr, "no space in this dialog.\n");
}


/*******************************************************************
 *クライアント画面拡大、操作に使用する関数
 *******************************************************************/

/*
  拡大表示を行う関数
 */
void
expanding_screen()
{
  if (window_ex == NULL) {
    SETVIEW(clientNum, TRUE);
    clientNum_ex = clientNum;
    window_ex = create_window_ex();
    GtkWidget *label_ex = lookup_widget(GTK_WIDGET(window_ex), "label_ex");
    GtkWidget *aspectframe = lookup_widget(GTK_WIDGET(window_ex), "aspectframe");
    drawingarea_ex = lookup_widget(GTK_WIDGET(window_ex), "drawingarea_ex");

    gtk_label_set_text (GTK_LABEL(label_ex), (gchar *)server_CB.client_grp[clientNum]->client_ID);
    gtk_widget_show(label_ex);

    float aspect = (float)server_CB.client_grp[clientNum_ex]->serverInitMsg.framebufferWidth / (float)server_CB.client_grp[clientNum_ex]->serverInitMsg.framebufferHeight;
    gtk_aspect_frame_set(GTK_ASPECT_FRAME(aspectframe), 0.5, 0.5, aspect, FALSE);
    gtk_window_set_default_size(GTK_WINDOW(window_ex), exwindowWidth, exwindowHeight);
    gtk_widget_show(aspectframe);

    gtk_widget_set_events (drawingarea_ex, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK
			| GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK
			| GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
			| GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK);

    smallimage_ex = gdk_image_new (GDK_IMAGE_FASTEST, gdkvis,
                         server_CB.client_grp[clientNum]->serverInitMsg.framebufferWidth,
                         server_CB.client_grp[clientNum]->serverInitMsg.framebufferHeight);

    gtk_widget_show(window_ex);
  } else if (clientNum_ex != clientNum) {
    SETVIEW(clientNum_ex, FALSE);
    SETCTRL(clientNum_ex, FALSE);
    GtkWidget *label_ex = lookup_widget(GTK_WIDGET(window_ex), "label_ex");
    GtkWidget *window_ex_togglebutton = lookup_widget(GTK_WIDGET(window_ex), "window_ex_togglebutton");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(window_ex_togglebutton), FALSE);
    clientNum_ex = clientNum;
    CreateImageInfo(TRUE);
    SETVIEW(clientNum_ex, TRUE);
    gdk_image_destroy(smallimage_ex);
    smallimage_ex = gdk_image_new (GDK_IMAGE_FASTEST, gdkvis,
				   server_CB.client_grp[clientNum_ex]->serverInitMsg.framebufferWidth,
				   server_CB.client_grp[clientNum_ex]->serverInitMsg.framebufferHeight);
    gtk_label_set_text(GTK_LABEL(label_ex), (gchar *)server_CB.client_grp[clientNum_ex]->client_ID);
    clientNum = clientNum_ex;
    draw_image(pixmap_ex, gdkGC, gdkimage[clientNum_ex], 0, 0, 0, 0,
               gdkimage[clientNum_ex]->width, gdkimage[clientNum_ex]->height);
  }
}


gboolean
on_window_ex_key_press_event             (GtkWidget       *widget,
                                        GdkEventKey     *event,
                                        gpointer         user_data)
{
  if (server_CB.client_grp[clientNum_ex] == NULL) return TRUE;
  if (!GETCTRL(clientNum_ex)) return TRUE;
  if ((GDK_Shift_L <= event->keyval) && (event->keyval <= GDK_Hyper_R)) {
    keyindex = (gint)(event->keyval - GDK_Shift_L);
    modifierPressed[keyindex] = TRUE;
  }

  //rfbsock = server_CB.client_grp[clientNum_ex]->vncdsp;
  clientNum = clientNum_ex;
  SendKeyEventSpecified(event->keyval, 1, server_CB.client_grp[clientNum_ex]->vncdsp);

  return TRUE;
}


gboolean
on_window_ex_key_release_event           (GtkWidget       *widget,
                                        GdkEventKey     *event,
                                        gpointer         user_data)
{
  if (server_CB.client_grp[clientNum_ex] == NULL) return TRUE;
  if (!GETCTRL(clientNum_ex)) return TRUE;
  if ((GDK_Shift_L <= event->keyval) && (event->keyval <= GDK_Hyper_R)) {
    keyindex = (gint)(event->keyval - GDK_Shift_L);
    modifierPressed[keyindex] = FALSE;
  }

  //rfbsock = server_CB.client_grp[clientNum_ex]->vncdsp;
  SendKeyEventSpecified(event->keyval, 0, server_CB.client_grp[clientNum_ex]->vncdsp);

  return TRUE;
}


gboolean
on_window_ex_focus_in_event              (GtkWidget       *widget,
                                        GdkEventFocus   *event,
                                        gpointer         user_data)
{

  return FALSE;
}


gboolean
on_window_ex_focus_out_event             (GtkWidget       *widget,
                                        GdkEventFocus   *event,
                                        gpointer         user_data)
{
  gint i;

  if (server_CB.client_grp[clientNum_ex] == NULL) return TRUE;
  if (!GETCTRL(clientNum_ex)) return TRUE;
  for (i = 0; i < 16; i++) {
    if (modifierPressed[i]) {
      //rfbsock = server_CB.client_grp[clientNum_ex]->vncdsp;
      SendKeyEventSpecified((guint)(i + GDK_Shift_L), FALSE, server_CB.client_grp[clientNum_ex]->vncdsp);
      modifierPressed[i] = FALSE;
    }
  }

  return TRUE;
}

gboolean
on_aspectframe_configure_event         (GtkWidget       *widget,
                                        GdkEventConfigure *event,
                                        gpointer         user_data)
{

  return FALSE;
}


gboolean
on_aspectframe_expose_event            (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data)
{

  return FALSE;
}



void
on_window_ex_togglebutton_toggled       (GtkToggleButton *togglebutton,
                                            gpointer         user_data)
{
  if (server_CB.client_grp[clientNum_ex] == NULL) return;
  if (gtk_toggle_button_get_active(togglebutton)) {
    SETCTRL(clientNum_ex, TRUE);
  } else {
    SETCTRL(clientNum_ex, FALSE);
  }
}


gboolean
on_window_ex_delete_event                (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  SETVIEW(clientNum_ex, FALSE);
  SETCTRL(clientNum_ex, FALSE);
  gdk_image_destroy(smallimage_ex);
  smallimage_ex = NULL;
  gtk_widget_destroy(window_ex);
  window_ex = NULL;
  free(iinfo_ex);
  iinfo_ex = NULL;

  return TRUE;
}


gboolean
on_drawingarea_ex_button_press_event   (GtkWidget       *widget,
                                        GdkEventButton  *event,
                                        gpointer         user_data)
{
  if (server_CB.client_grp[clientNum_ex] == NULL) return TRUE;
  GtkWidget *menu;
  int resize_x, resize_y;
  int p = server_CB.client_grp[clientNum_ex]->draw_page;
  int d = server_CB.client_grp[clientNum_ex]->draw_area;

  if (GETCTRL(clientNum_ex)) {
    resize_x = (iinfo_ex->widthDstToSrc * (int)event->x) >> SHIFTVAL;
    resize_y = (iinfo_ex->heightDstToSrc * (int)event->y) >> SHIFTVAL;
    //rfbsock = server_CB.client_grp[clientNum_ex]->vncdsp;
    SendPointerEventSpecified(resize_x, resize_y, (((event->state & (GDK_BUTTON1_MASK |
		     GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
		     GDK_BUTTON5_MASK)) >> 8) | (1 << (event->button - 1))), server_CB.client_grp[clientNum_ex]->vncdsp);
  }
  else if (event->button == 3) {
    menu = create_rightclickmenu2((gpointer)(100*p+d));
    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
		   event->button, event->time);
  }

  return TRUE;
}


gboolean
on_drawingarea_ex_button_release_event (GtkWidget       *widget,
                                        GdkEventButton  *event,
                                        gpointer         user_data)
{
  int resize_x, resize_y;

  if (server_CB.client_grp[clientNum_ex] == NULL) return TRUE;
  if (GETCTRL(clientNum_ex)) {
    resize_x = (iinfo_ex->widthDstToSrc * (int)event->x) >> SHIFTVAL;
    resize_y = (iinfo_ex->heightDstToSrc * (int)event->y) >> SHIFTVAL;
    //rfbsock = server_CB.client_grp[clientNum_ex]->vncdsp;
    SendPointerEventSpecified(resize_x, resize_y, (((event->state & (GDK_BUTTON1_MASK |
		     GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
		     GDK_BUTTON5_MASK)) >> 8) & ~(1 << (event->button - 1))), server_CB.client_grp[clientNum_ex]->vncdsp);
  }

  return TRUE;
}


gboolean
on_drawingarea_ex_configure_event      (GtkWidget       *widget,
                                        GdkEventConfigure *event,
                                        gpointer         user_data)
{
  if (pixmap_ex)
    gdk_pixmap_unref(pixmap_ex);

  pixmap_ex = gdk_pixmap_new(widget->window,
			     widget->allocation.width,
			     widget->allocation.height, -1);

  gdk_draw_rectangle(pixmap_ex, widget->style->white_gc, TRUE,
		     0, 0, widget->allocation.width, widget->allocation.height);

  CreateImageInfo(TRUE);
  clientNum = clientNum_ex;
  draw_image(pixmap_ex, gdkGC, gdkimage[clientNum], 0, 0, 0, 0,
             gdkimage[clientNum]->width, gdkimage[clientNum]->height);

  return TRUE;
}


gboolean
on_drawingarea_ex_expose_event         (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data)
{
  gdk_draw_pixmap(widget->window,
		  widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
		  pixmap_ex,
		  event->area.x, event->area.y,
		  event->area.x, event->area.y,
		  event->area.width, event->area.height);

  return FALSE;
}


gboolean
on_drawingarea_ex_motion_notify_event    (GtkWidget       *widget,
                                        GdkEventMotion  *event,
                                        gpointer         user_data)
{
  int x, y, resize_x, resize_y;
  GdkModifierType state;

  if (server_CB.client_grp[clientNum_ex] == NULL) return TRUE;
  if (!GETCTRL(clientNum_ex)) return TRUE;
  if (event->is_hint){
    gdk_window_get_pointer(event->window, &x, &y, &state);
    resize_x = (iinfo_ex->widthDstToSrc * x) >> SHIFTVAL;
    resize_y = (iinfo_ex->heightDstToSrc * y) >> SHIFTVAL;
    //rfbsock = server_CB.client_grp[clientNum_ex]->vncdsp;
    SendPointerEventSpecified(resize_x, resize_y, ((state & (GDK_BUTTON1_MASK |
                     GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
                     GDK_BUTTON5_MASK)) >> 8), server_CB.client_grp[clientNum_ex]->vncdsp);
  }

  return TRUE;
}


/*******************************************************************
 *右クリックメニュー
 *******************************************************************/

/*
  メインウィンドウでの右クリックメニュー
 */
GtkWidget*
create_rightclickmenu1 (gpointer user_data)
{
  int c_num = clientNum;
  GtkWidget *rightclickmenu1;
  GtkWidget *viewset;
  GtkWidget *screen_expand;
  GtkWidget *screen_ctrl;
  GtkWidget *screen_lock;
  GtkWidget *screen_send;
  GtkWidget *screen_send_stop;
//  GtkWidget *screen_record;

  rightclickmenu1 = gtk_menu_new ();

  viewset = gtk_menu_item_new_with_mnemonic (_("Preferences of View"));
  gtk_widget_show (viewset);
  gtk_container_add (GTK_CONTAINER (rightclickmenu1), viewset);

  screen_expand = gtk_menu_item_new_with_mnemonic (_("Expand"));
  gtk_widget_show (screen_expand);
  gtk_container_add (GTK_CONTAINER (rightclickmenu1), screen_expand);

  screen_ctrl = gtk_menu_item_new_with_mnemonic (_("Operate"));
  gtk_widget_show (screen_ctrl);
  gtk_container_add (GTK_CONTAINER (rightclickmenu1), screen_ctrl);

  screen_lock = gtk_menu_item_new_with_mnemonic (_("Lock/Unlock"));
  gtk_widget_show (screen_lock);
  gtk_container_add (GTK_CONTAINER (rightclickmenu1), screen_lock);

  screen_send = gtk_menu_item_new_with_mnemonic (_("Send screen"));
  gtk_widget_show (screen_send);
  gtk_container_add (GTK_CONTAINER (rightclickmenu1), screen_send);

  screen_send_stop = gtk_menu_item_new_with_mnemonic (_("Stop sending"));
  gtk_widget_show (screen_send_stop);
  gtk_container_add (GTK_CONTAINER (rightclickmenu1), screen_send_stop);

//  screen_record = gtk_menu_item_new_with_mnemonic (_("Record screen"));
//  gtk_widget_show (screen_record);
//  gtk_container_add (GTK_CONTAINER (rightclickmenu1), screen_record);

  g_signal_connect ((gpointer) viewset, "activate",
                    G_CALLBACK (on_viewset_activate),
                    NULL);
  g_signal_connect ((gpointer) screen_expand, "activate",
                    G_CALLBACK (on_screen_expand_activate),
                    (gpointer)c_num);
  g_signal_connect ((gpointer) screen_ctrl, "activate",
                    G_CALLBACK (on_screen_ctrl_activate),
                    (gpointer)c_num);
  g_signal_connect ((gpointer) screen_lock, "activate",
                    G_CALLBACK (on_screen_lock_activate),
                    (gpointer)c_num);
  g_signal_connect ((gpointer) screen_send, "activate",
                    G_CALLBACK (on_screen_send_activate),
                    user_data);
  g_signal_connect ((gpointer) screen_send_stop, "activate",
                    G_CALLBACK (on_screen_send_stop_activate),
                    (gpointer)c_num);
//  g_signal_connect ((gpointer) screen_record, "activate",
//                    G_CALLBACK (on_screen_record_activate),
//                    (gpointer)c_num);

  return rightclickmenu1;
}


/*
  拡大表示用ウィンドウでの右クリックメニュー
 */
GtkWidget*
create_rightclickmenu2 (gpointer user_data)
{
  GtkWidget *rightclickmenu2;
  GtkWidget *menuitem3;
  GtkWidget *menuitem4;
  GtkWidget *menuitem5;
  GtkWidget *menuitem6;

  rightclickmenu2 = gtk_menu_new ();

  menuitem3 = gtk_menu_item_new_with_mnemonic (_("Operate"));
  gtk_widget_show (menuitem3);
  gtk_container_add (GTK_CONTAINER (rightclickmenu2), menuitem3);

  menuitem4 = gtk_menu_item_new_with_mnemonic (_("Lock/Unlock"));
  gtk_widget_show (menuitem4);
  gtk_container_add (GTK_CONTAINER (rightclickmenu2), menuitem4);

  menuitem5 = gtk_menu_item_new_with_mnemonic (_("Send screen"));
  gtk_widget_show (menuitem5);
  gtk_container_add (GTK_CONTAINER (rightclickmenu2), menuitem5);

  menuitem6 = gtk_menu_item_new_with_mnemonic (_("Stop sending screen"));
  gtk_widget_show (menuitem6);
  gtk_container_add (GTK_CONTAINER (rightclickmenu2), menuitem6);

  g_signal_connect ((gpointer) menuitem3, "activate",
                    G_CALLBACK (on_screen_ctrl_activate),
                    (gpointer)clientNum_ex);
  g_signal_connect ((gpointer) menuitem4, "activate",
                    G_CALLBACK (on_screen_lock_activate),
                    (gpointer)clientNum_ex);
  g_signal_connect ((gpointer) menuitem5, "activate",
                    G_CALLBACK (on_screen_send_activate),
                    user_data);
  g_signal_connect ((gpointer) menuitem6, "activate",
                    G_CALLBACK (on_screen_send_stop_activate),
                    (gpointer)clientNum_ex);

  return rightclickmenu2;
}


void
on_screen_expand_activate              (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  clientNum = (int)user_data;
  SETCTRL(clientNum, FALSE);
  expanding_screen();
  GtkWidget *window_ex_togglebutton = lookup_widget(GTK_WIDGET(window_ex), "window_ex_togglebutton");
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(window_ex_togglebutton), FALSE);
}


void
on_screen_ctrl_activate                (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  clientNum = (int)user_data;
  expanding_screen();
  GtkWidget *window_ex_togglebutton = lookup_widget(GTK_WIDGET(window_ex), "window_ex_togglebutton");
  if (!GETCTRL(clientNum)) {
    SETCTRL(clientNum, TRUE);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(window_ex_togglebutton), TRUE);
  } else {
    SETCTRL(clientNum, FALSE);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(window_ex_togglebutton), FALSE);
  }
  //printf("clientNum=%d\n", clientNum);
}


void
on_screen_lock_activate                (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  int c_num = (int)user_data;

  if (strcmp((char *)server_CB.client_grp[c_num]->client_ID, (char *)server_CB.server_ID) == 0) return;
  SETLOCK(c_num, !GETLOCK(c_num));
  SendLockMsg(GETLOCK(c_num), c_num);
}


void
on_screen_send_activate                (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  int p = ((int)user_data & 0xff00) >> 8;
  int d = (int)user_data & 0x00ff;

  if (GETSEND(draw_info[p].client_num[d])) {
    printf("This client is already source.\n");
    return;
  } else {
    on_send_activate(menuitem, NULL);
    gtk_entry_set_text (GTK_ENTRY (GTK_BIN(dialog_send_comboboxentry1)->child), _(draw_info[p].group_name));
    gtk_entry_set_text (GTK_ENTRY (GTK_BIN(dialog_send_comboboxentry2)->child),
		        _((char *)server_CB.client_grp[draw_info[p].client_num[d]]->client_ID));
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), FALSE);
    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dialog_send_checkbutton2[p][d]), TRUE);
    if (strcmp((char *)server_CB.client_grp[draw_info[p].client_num[d]]->client_ID, (char *)server_CB.server_ID) != 0)
      src_checkbutton = dialog_send_checkbutton2[p][d];
  }
}


void
on_screen_send_stop_activate           (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  on_send_activate(menuitem, NULL);

  // open 2 page
  GtkWidget *notebook = lookup_widget(dialog_send, "notebook");
  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 1);
}


#if 0
/*******************************************************************
 *画面録画ダイアログで使用される関数
 *******************************************************************/
void
on_screen_record_activate              (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
  int pCnt, dCnt, flag = 0;
  dialog_record = create_dialog_record();
  dialog_record_table = makeTable_userList();
  GtkWidget *checkbutton0 = lookup_widget(dialog_record, "dialog_record_checkbutton0");

  // can't setting resolution (widget hide)
  GtkWidget *hbox5 = lookup_widget(dialog_record, "hbox5");
  gtk_widget_hide(hbox5);

  for (pCnt = 0; pCnt < tab_num; pCnt++) {
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if (draw_info[pCnt].client_num[dCnt] == EMPTY) continue;
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[pCnt][dCnt]), \
		      GETREC(draw_info[pCnt].client_num[dCnt])); g_signal_connect ((gpointer) dialog_send_checkbutton2[pCnt][dCnt], "toggled",
		      G_CALLBACK (on_dialog_lock_checkbutton2_toggled), 
		      (gpointer) ((pCnt << 8)+dCnt));
      flag += gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON ( dialog_send_checkbutton2[pCnt][dCnt]));
    }
    g_signal_connect ((gpointer) dialog_send_checkbutton1[pCnt], "toggled", 
		    G_CALLBACK (on_dialog_lock_checkbutton1_toggled),
		    (gpointer) pCnt);
    g_signal_connect ((gpointer) checkbutton0, "toggled", 
		    G_CALLBACK (on_dialog_lock_checkbutton0_toggled),
		    (gpointer) pCnt);
  }

  // start or stop record button hide
  if (flag) {
    GtkWidget *button_record_start = lookup_widget(dialog_record, "button_record_start");
    gtk_widget_hide(button_record_start);
  }
  else {
    GtkWidget *button_record_stop = lookup_widget(dialog_record, "button_record_stop");
    gtk_widget_hide(button_record_stop);
  }
  GtkWidget *dialog_record_viewport = lookup_widget(GTK_WIDGET(dialog_record), "dialog_record_viewport");
  gtk_container_add (GTK_CONTAINER (dialog_record_viewport), dialog_record_table);
  gtk_widget_show(dialog_record_table);
  gtk_widget_show(dialog_record);
  gtk_grab_add(dialog_record);
}


void
on_dialog_rec_start_button_clicked     (GtkButton       *button,
                                        gpointer         user_data)
{
  // start <-> stop change
  GtkWidget *button_record_start = lookup_widget(dialog_record, "button_record_start");
  GtkWidget *button_record_stop = lookup_widget(dialog_record, "button_record_stop");
  gtk_widget_hide(button_record_start);
  gtk_widget_show(button_record_stop);

  // get recording time, FPS, and resolution
  GtkWidget *sppinbutton_record = lookup_widget(GTK_WIDGET(dialog_record), "spinbutton_rec_time");
  GtkWidget *spinbutton_fps = lookup_widget(GTK_WIDGET(dialog_record), "spinbutton_fps");
  GtkWidget *combo_entry = lookup_widget(GTK_WIDGET(dialog_record), "combo_entry1");

  int rec_time = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sppinbutton_record));
  int fps = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinbutton_fps));
  gchar geometry[IDLENGTH];
  strcpy(geometry, gtk_entry_get_text (GTK_ENTRY(combo_entry))); 

  printf("recording time:%d, fps:%d, geometry(resolution):%s\n", rec_time, fps, geometry);

  recording(rec_time, fps, geometry);
}


void
on_dialog_rec_stop_button_clicked      (GtkButton       *button,
                                        gpointer         user_data)
{
  // start <-> stop change
  GtkWidget *button_record_start = lookup_widget(dialog_record, "button_record_start");
  GtkWidget *button_record_stop = lookup_widget(dialog_record, "button_record_stop");
  gtk_widget_show(button_record_start);
  gtk_widget_hide(button_record_stop);

  // all chech button clear
  GtkWidget *checkbutton0 = lookup_widget(dialog_record, "dialog_record_checkbutton0");
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton0), TRUE);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton0), FALSE);

  recording(-1, -1, "");
}


void
on_dialog_rec_close_button_clicked     (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_record);
  gtk_widget_destroy(dialog_record);
}


gboolean
on_dialog_record_delete_event          (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_record);
  gtk_widget_destroy(dialog_record);
  return TRUE;
}


int
recording (int rec_time, int fps, char *geometry)
{
  int p, d, num, rec_flag;

  for (p = 0; p < tab_num; p++) {
    for (d = 0; d < TABGROUP_MAX; d++) {
      if ((num= draw_info[p].client_num[d]) == EMPTY) continue;

      rec_flag = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]));

      printf("#####[rec control:client:%d(%s) flag %d]#####\n", num, inet_ntoa(server_CB.client_grp[num]->client_ip), rec_flag);
      if (rec_time > 0 && (GETREC(num) || rec_flag)) {
        // record start
        SendRecMsg(START, server_CB.client_grp[num]->ctldsp, rec_time, fps, geometry);
        SETREC(num, START);
      } else if (rec_time < 0) {
        // record stop
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), FALSE);
        SendRecMsg(STOP, server_CB.client_grp[num]->ctldsp, 0, 0, NULL);
	SETREC(num, STOP);
      }
    }
  }
  return 0;
}

#endif

/*******************************************************************
 *送信設定ダイアログで使用される関数
 *******************************************************************/

/*
  送信元が所属しているグループを決定するためのcomboboxウィジェットの作成
 */
void makeCombobox1_dialog_send(void)
{
  int pCnt;
  GtkWidget *dialog_send_hbox = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_hbox");

  dialog_send_comboboxentry1 = gtk_combo_box_entry_new_text ();
  gtk_widget_show (dialog_send_comboboxentry1);
  gtk_box_pack_start (GTK_BOX (dialog_send_hbox), dialog_send_comboboxentry1, TRUE, TRUE, 0);
  g_signal_connect ((gpointer) dialog_send_comboboxentry1, "changed",
		    G_CALLBACK (on_dialog_send_comboboxentry1_changed),
		    NULL);
  for (pCnt = 0; pCnt < tab_num; pCnt++)
    gtk_combo_box_append_text (GTK_COMBO_BOX (dialog_send_comboboxentry1), _(draw_info[pCnt].group_name));

  dialog_send_label_ID = gtk_label_new (_("User ID"));
  gtk_widget_show (dialog_send_label_ID);
  gtk_box_pack_start (GTK_BOX (dialog_send_hbox), dialog_send_label_ID, FALSE, FALSE, 0);
}


/*
  送信元クライアントを決定するためのcomboboxウィジェットの作成
 */
void makeCombobox2_dialog_send(void)
{
  GtkWidget *dialog_send_hbox = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_hbox");
  dialog_send_comboboxentry2 = gtk_combo_box_entry_new_text ();
  gtk_widget_show (dialog_send_comboboxentry2);
  gtk_box_pack_start (GTK_BOX (dialog_send_hbox), dialog_send_comboboxentry2, TRUE, TRUE, 0);

  g_signal_connect ((gpointer) dialog_send_comboboxentry2, "changed",
		    G_CALLBACK (on_dialog_send_comboboxentry2_changed),
		    NULL);
}


/*
  「送信設定」タブでユーザ一覧を表示するためのtableウィジェットの作成
 */
GtkWidget *makeTable_userList(void)
{
  int pCnt, dCnt, c_num;
  char tab[16]; // TAB_MAX ?
  GtkWidget *table;
  GtkWidget *label;
  GtkWidget *vbox[TAB_MAX];
  GtkWidget *hseparator[TAB_MAX-1];

  /* table の作成 */
  table = gtk_table_new(2*tab_num-1, 3, FALSE);

  for (pCnt = 0; pCnt < tab_num; pCnt++) {
    /* セパレータの作成 */
    if (pCnt != 0) {
      hseparator[pCnt] = gtk_hseparator_new ();
      gtk_widget_show (hseparator[pCnt]);
      gtk_table_attach (GTK_TABLE (table), hseparator[pCnt], 0, 3, 2*pCnt-1, 2*pCnt,
		        (GtkAttachOptions) (GTK_FILL),
		        (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
    }

    /* label "tab x" */
    sprintf(tab, _("tab %d"), pCnt+1);
    label = gtk_label_new (_(tab));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2*pCnt, 2*pCnt+1,
		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
		      (GtkAttachOptions) (GTK_FILL), 0, 0);

    /* グループ送信用check button の作成 */
    dialog_send_checkbutton1[pCnt] = gtk_check_button_new_with_mnemonic (_(draw_info[pCnt].group_name));
    gtk_widget_show (dialog_send_checkbutton1[pCnt]);
    gtk_table_attach (GTK_TABLE (table), dialog_send_checkbutton1[pCnt], 1, 2, 2*pCnt, 2*pCnt+1,
		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
		      (GtkAttachOptions) (GTK_FILL), 0, 0);

    vbox[pCnt] = gtk_vbox_new(FALSE, 0);
    gtk_widget_show(vbox[pCnt]);
    gtk_table_attach (GTK_TABLE (table), vbox[pCnt], 2, 3, 2*pCnt, 2*pCnt+1,
		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
		      (GtkAttachOptions) (GTK_FILL), 0, 0);

    /* 個人送信用check button の作成 */
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if ((c_num = draw_info[pCnt].client_num[dCnt]) == EMPTY) continue;
      dialog_send_checkbutton2[pCnt][dCnt] = gtk_check_button_new_with_mnemonic (_((char *)server_CB.client_grp[c_num]->client_ID));
      gtk_widget_show (dialog_send_checkbutton2[pCnt][dCnt]);
      gtk_box_pack_start(GTK_BOX(vbox[pCnt]), dialog_send_checkbutton2[pCnt][dCnt], TRUE, TRUE, 0);
    }
  }
  
  return table;
}


/*
  「送信状態」タブでユーザ一覧を表示するためのtableウィジェットの作成
 */
GtkWidget *makeTable_send_state(void)
{
  int mcCnt, dstCnt, castnum, src_num;
  GtkWidget *table;
  GtkWidget *hseparator;
  GtkWidget *dialog_send_checkbutton3[MAXCLIENT];
  GtkWidget *vbox[MAXCLIENT];

  /* tableの作成 */
  table = gtk_table_new(1, 2, FALSE);
  mcCnt = 0;
  for (castnum = 0; castnum < MAXCLIENT; castnum++) {
    if (server_CB.cast_src[castnum] != EMPTY) {
      src_num = server_CB.cast_src[castnum];

      if (mcCnt != 0) {
        /* tableのリサイズ */
        gtk_table_resize(GTK_TABLE(table), 2*mcCnt-1, 2);
	/* セパレータの作成 */
	hseparator = gtk_hseparator_new ();
	gtk_widget_show (hseparator);
	gtk_table_attach (GTK_TABLE (table), hseparator, 0, 3, 2*mcCnt-1, 2*mcCnt,
			  (GtkAttachOptions) (GTK_FILL),
			  (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
      }

      /* 送信元の送信状態を決定するためのcheck buttonの作成 */
      dialog_send_checkbutton3[castnum] = gtk_check_button_new_with_mnemonic (_((char *)server_CB.client_grp[src_num]->client_ID));
      gtk_widget_show (dialog_send_checkbutton3[castnum]);
      gtk_table_attach (GTK_TABLE (table), dialog_send_checkbutton3[castnum], 0, 1, 2*mcCnt, 2*mcCnt+1,
		        (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
		        (GtkAttachOptions) (GTK_FILL), 0, 0);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton3[castnum]), GETSEND(server_CB.cast_src[castnum]));
      g_signal_connect ((gpointer) dialog_send_checkbutton3[castnum], "toggled",
		        G_CALLBACK (on_dialog_send_checkbutton3_toggled),
		        (gpointer) castnum);

      vbox[castnum] = gtk_vbox_new(FALSE, 0);
      gtk_widget_show(vbox[castnum]);
      gtk_table_attach (GTK_TABLE (table), vbox[castnum], 1, 2, 2*mcCnt, 2*mcCnt+1,
		        (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
		        (GtkAttachOptions) (GTK_FILL), 0, 0);

      mcCnt++;
    }
  }

  /* 送信先の送信状態を決定するためのcheck buttonの作成 */
  for (dstCnt = 0; dstCnt < MAXCLIENT; dstCnt++) {
    if (server_CB.client_grp[dstCnt] == NULL) continue;
    if ((server_CB.client_grp[dstCnt]->recv_grp != EMPTY)) {
      dialog_send_checkbutton4[dstCnt] = gtk_check_button_new_with_mnemonic (_((char *)server_CB.client_grp[dstCnt]->client_ID));
      gtk_widget_show (dialog_send_checkbutton4[dstCnt]);
      gtk_box_pack_start(GTK_BOX(vbox[server_CB.client_grp[dstCnt]->recv_grp]), dialog_send_checkbutton4[dstCnt], TRUE, TRUE, 0);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton4[dstCnt]), GETRECV(dstCnt));
      g_signal_connect ((gpointer) dialog_send_checkbutton4[dstCnt], "toggled",
		        G_CALLBACK (on_dialog_send_checkbutton4_toggled),
		        (gpointer) (dstCnt));
    }
  }

  return table;
}


gboolean
on_dialog_send_delete_event                (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_send);
  gtk_widget_destroy(dialog_send);

  return TRUE;
}


/*
  グループ送信用のcheck buttonがクリックされた時に呼び出される.
 */
void on_dialog_send_checkbutton1_toggled                (GtkToggleButton *togglebutton,
		                                     gpointer         user_data)
{
  int p = (int)user_data;
  int d, num;
  gboolean active_flag;

  active_flag = gtk_toggle_button_get_active(togglebutton);
  for (d = 0; d < TABGROUP_MAX; d++) {
    if ((num = draw_info[p].client_num[d]) == EMPTY) continue;
    if ((dialog_send_checkbutton2[p][d] == src_checkbutton) || (GETRECV(num))) continue;
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), active_flag);
  } 
}


/*
  個人送信用のcheck buttonがクリックされた時に呼び出される.
 */
void on_dialog_send_checkbutton2_toggled                (GtkToggleButton *togglebutton,
		                                     gpointer         user_data)
{
  int p = ((int)user_data & 0xff00) >> 8;
  int d = (int)user_data & 0x00ff;

  if (togglebutton == GTK_TOGGLE_BUTTON(src_checkbutton))
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), FALSE);
  else if (GETRECV(draw_info[p].client_num[d]))
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), GETRECV(draw_info[p].client_num[d]));
}


/*
  送信元の送信状態を決定するcheck buttonがクリックされた時に呼び出される.
 */
void on_dialog_send_checkbutton3_toggled                (GtkToggleButton *togglebutton,
		                                     gpointer         user_data)
{
  int mc = (int)user_data;
  int d, user_cnt = 0;
  gboolean active_flag;

  active_flag = gtk_toggle_button_get_active(togglebutton);
  send_state_tmp[server_CB.cast_src[mc]] = active_flag;
  for (d = 0; d < MAXCLIENT; d++) {
    if (server_CB.client_grp[d] == NULL) continue;
    if (server_CB.client_grp[d]->recv_grp != mc) continue;
    recv_state_tmp[d] = active_flag;
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton4[d]), active_flag);
    if (server_CB.user_num == ++user_cnt) break;
  }
}


/*
  送信先の送信状態を決定するcheck buttonがクリックされた時に呼び出される.
 */
void on_dialog_send_checkbutton4_toggled                (GtkToggleButton *togglebutton,
		                                     gpointer         user_data)
{
  int d = (int)user_data;

  if (gtk_toggle_button_get_active(togglebutton)){
    if (send_state_tmp[server_CB.cast_src[server_CB.client_grp[d]->recv_grp]])
      recv_state_tmp[d] = TRUE;
    else
      gtk_toggle_button_set_active(togglebutton, FALSE);
  } else
    recv_state_tmp[d] = FALSE;
}


/*
  全体送信用のcheck buttonがクリックされた時に呼び出される.
 */
void
on_dialog_send_checkbutton0_toggled        (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
  int p, d, num;
  gboolean active_flag;

  active_flag = gtk_toggle_button_get_active(togglebutton);
  for (p = 0; p < tab_num; p++) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton1[p]), active_flag);
    for (d = 0; d < TABGROUP_MAX; d++) {
      if ((num = draw_info[p].client_num[d]) == EMPTY) continue;
      if ((dialog_send_checkbutton2[p][d] == src_checkbutton) || (GETRECV(num))) continue;
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), active_flag);
    }
  }
}


/*
  送信元クライアントが所属するグループを決定するcombo boxが変化した時に呼び出される.
 */
void
on_dialog_send_comboboxentry1_changed      (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
  int p, i, num;
  char *string;
  GtkWidget *dialog_send_hbox = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_hbox");

  if (src_checkbutton != NULL)
    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (src_checkbutton), FALSE);
  src_checkbutton = NULL;
  string = (char *)gtk_entry_get_text(GTK_ENTRY(GTK_BIN(combobox)->child));
  gtk_container_remove(GTK_CONTAINER(dialog_send_hbox), dialog_send_comboboxentry2);
  makeCombobox2_dialog_send();
  for (p = 0; p < tab_num; p++) {
    if (strcmp(draw_info[p].group_name, string) == 0) {
      for (i = 0; i < TABGROUP_MAX; i++) {
	num = draw_info[p].client_num[i];
	if (num == EMPTY) continue;
	if (!GETSEND(num)) {
	  gtk_combo_box_append_text (GTK_COMBO_BOX (dialog_send_comboboxentry2),
				     _((char *)server_CB.client_grp[num]->client_ID));
	}
      }
      return;
    }
  }
}


/*
  送信元クライアントを決定するcombo boxが変化した時に呼び出される.
 */
void
on_dialog_send_comboboxentry2_changed      (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
  int p, d;
  char *client_name;

  if (src_checkbutton != NULL)
    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (src_checkbutton), FALSE);
  src_checkbutton = NULL;
  client_name = (char *)gtk_entry_get_text(GTK_ENTRY(GTK_BIN(combobox)->child));
  if (client_name != NULL) {
    for (p = 0; p < tab_num; p++) {
      for (d = 0; d < TABGROUP_MAX; d++) {
	if (draw_info[p].client_num[d] == EMPTY) continue;
        if ((strcmp((char *)server_CB.client_grp[draw_info[p].client_num[d]]->client_ID, client_name) == 0) && (strcmp((char *)server_CB.server_ID, client_name) != 0)) {
	  src_checkbutton = dialog_send_checkbutton2[p][d];
	  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (src_checkbutton), TRUE);
	  return;
	}
      }
    }
  }
}


void
on_dialog_send_buttonOK_clicked            (GtkButton       *button,
                                        gpointer         user_data)
{
  send_start();

  gtk_grab_remove(dialog_send);
  gtk_widget_destroy(dialog_send);
}


/*
  ダイアログの内容の通りに送信を行う関数.
 */
void
send_start(void)
{
  int user_cnt, src_client = 0, mcnum, c_num, i, m, p, d;
  char *client_name;
  gboolean send_flag = FALSE;
  gboolean recv_flag = FALSE;

  /* 送信元クライアントの探索 */
  client_name = (char *)gtk_entry_get_text(GTK_ENTRY(GTK_BIN(dialog_send_comboboxentry2)->child));
  if (client_name != NULL) {
    for (src_client = 0; src_client < MAXCLIENT; src_client++) {
      if (server_CB.client_grp[src_client] == NULL) continue;
      if (strcmp((char *)server_CB.client_grp[src_client]->client_ID, client_name) == 0) {
        send_flag = TRUE;
	break;
      }
    }
  }

  /* 使用できるマルチキャストグループ番号を探索 */
  for (mcnum = 0; mcnum < MAXCLIENT; mcnum++) {
    if (server_CB.cast_src[mcnum] == EMPTY) break;
  }

  /* 送信元と送信先がともに存在する時に限り, 新規にマルチキャストグループを
     生成する. 
   */
  if (send_flag) {
    for (p = 0; p < tab_num; p++) {
      for (d = 0; d < TABGROUP_MAX; d++) {
	if ((c_num = draw_info[p].client_num[d]) == EMPTY) continue;
	if (strcmp((char *)server_CB.client_grp[c_num]->client_ID, (char *)server_CB.server_ID) == 0) continue;
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]))) {
	  if ((m = server_CB.client_grp[src_client]->cast_grp) != EMPTY) {
	    server_CB.cast_src[m] = EMPTY;
	    server_CB.client_grp[src_client]->cast_grp = EMPTY;
	    user_cnt = 0;
	    for (i = 0; i < MAXCLIENT; i++) {
	      if (server_CB.client_grp[i] == NULL) continue;
	      if (server_CB.client_grp[i]->recv_grp == m) {
		server_CB.client_grp[i]->recv_grp = EMPTY;
	      }
	      if (server_CB.user_num == ++user_cnt) break;
	    }
          }
	  server_CB.client_grp[c_num]->recv_grp = mcnum;
	  recv_state_tmp[c_num] = TRUE;
	  recv_flag = TRUE;
        }
      }
    }
    if (recv_flag) {
      send_state_tmp[src_client] = TRUE;
      server_CB.cast_src[mcnum] = src_client;
      server_CB.client_grp[src_client]->cast_grp = mcnum;
    }
  }

  /*
    送信元クライアントの設定
   */
  user_cnt = 0;
  for (c_num = 0; c_num < MAXCLIENT; c_num++) {
    if (server_CB.client_grp[c_num] == NULL) continue;
    if ((send_state_tmp[c_num] && !GETSEND(c_num)) || (!send_state_tmp[c_num] && GETSEND(c_num))) {
      SETSEND(c_num, send_state_tmp[c_num]);
      if (GETSEND(c_num)) {
	int pchild;
	int shm_id;
	int shm_key = mcnum;
        server_CB.cstdsp[mcnum] = CreateMultiSockToSend (server_CB.casting_ip[mcnum], server_CB.casting_port);

	printf("mcnum=%d %d\n",mcnum,shm_key);
	do {
	  shm_id = shmget ((key_t)shm_key, sizeof(struct Shm_asym), 0666 | IPC_CREAT);
	  if (shm_id == -1) {
	    fprintf(stderr, "error : shm_id errno=%d key(grp)=%d clientNum=%d\n",errno,shm_key,c_num);
	    shm_key++;
	    printf("err:mcnum=%d %d\n",mcnum,shm_key);
	    //return;
	  }
	} while (shm_id < 0);
	
	shm_asym[c_num] = (struct Shm_asym *)shmat(shm_id, 0, 0);
	if ((int)shm_asym[c_num] == -1) {
	  fprintf(stderr, "error : shm_asym[%d]\n",c_num);
	  return;
	}
	bzero(shm_asym[c_num], sizeof(struct Shm_asym));
	(*shm_asym[c_num]).ave_delay = 0;
	server_CB.client_grp[c_num]->shm_id = shm_id;

	if ((pchild = fork()) == 0) {
	  /* Child */
	  SendCast(c_num);
	  exit (0);
	}
	server_CB.client_grp[c_num]->calcrate_tag = \
	  gtk_timeout_add (CALC_INTERVAL, (GtkFunction)calcRateCallback, (gpointer)c_num);
	if (Resend_flag)
	  server_CB.client_grp[c_num]->resend_tag = \
	    gtk_timeout_add (RESEND_INTERVAL, (GtkFunction)resendCallback, (gpointer)c_num);
	calcRateCallback ((gpointer)c_num);
	SendAllowMsg(c_num, (char *)server_CB.client_grp[c_num]->client_ID);
      } else {
	(*shm_asym[c_num]).flag = CAST_STOP;
	int shmctlck;
	int res = shmdt(shm_asym[c_num]);
	shmctlck = shmctl(server_CB.client_grp[c_num]->shm_id, IPC_RMID, 0);
	printf("shm_deleted.(%d) ctlck=%d(errno=%d) client=%d grp=%d\n", \
	    res,shmctlck,errno,c_num,server_CB.client_grp[c_num]->cast_grp);
	server_CB.cast_src[server_CB.client_grp[c_num]->cast_grp] == EMPTY;
	shm_asym[c_num] = NULL;

	gtk_timeout_remove (server_CB.client_grp[c_num]->calcrate_tag);
	if (Resend_flag)
	  gtk_timeout_remove (server_CB.client_grp[c_num]->resend_tag);
        close (server_CB.cstdsp[server_CB.client_grp[c_num]->cast_grp]);
      }
    }
    if (server_CB.user_num == ++user_cnt) break;
  }
  /*
    送信先クライアントの設定, 各クライアントに通知
   */
  user_cnt = 0;
  for (c_num = 0; c_num < MAXCLIENT; c_num++) {
    if (server_CB.client_grp[c_num] == NULL) continue;
    if ((!recv_state_tmp[c_num] && GETRECV(c_num)) || (recv_state_tmp[c_num] && !GETRECV(c_num))) {
      SETRECV(c_num, recv_state_tmp[c_num]);
      SendCastMsg(GETRECV(c_num), c_num, fullscreen_flag);
    }
    if (server_CB.user_num == ++user_cnt) break;
  }

  /*
    送信元クライアントの画像データを要求
   */
  user_cnt = 0;
  for (c_num = 0; c_num < MAXCLIENT; c_num++) {
    if (server_CB.client_grp[c_num] == NULL) continue;
    if (GETSEND(c_num)) {
      //rfbsock = server_CB.client_grp[c_num]->vncdsp;
      clientNum = c_num;
      if (SendAllFramebufferUpdateRequestSpecified(server_CB.client_grp[c_num]->vncdsp) < 0) {
	printf("error : SendAllFramebufferUpdateRequest\n");
      }
    }
    if (server_CB.user_num == ++user_cnt) break;
  }
}

void
on_dialog_send_buttonCancel_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_send);
  gtk_widget_destroy(dialog_send);
}


void
on_dialog_send_buttonApply_clicked         (GtkButton       *button,
                                        gpointer         user_data)
{
  int Cnt, pCnt, dCnt;
  int user_cnt = 0;
  GtkWidget *dialog_send_hbox = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_hbox");
  GtkWidget *dialog_send_viewport1 = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_viewport1");
  GtkWidget *dialog_send_viewport2 = lookup_widget(GTK_WIDGET(dialog_send), "dialog_send_viewport2");

  send_start();

  gtk_container_remove(GTK_CONTAINER(dialog_send_hbox), dialog_send_comboboxentry1);
  gtk_container_remove(GTK_CONTAINER(dialog_send_hbox), dialog_send_label_ID);
  gtk_container_remove(GTK_CONTAINER(dialog_send_hbox), dialog_send_comboboxentry2);
  gtk_container_remove(GTK_CONTAINER(dialog_send_viewport1), dialog_send_table1);
  gtk_container_remove(GTK_CONTAINER(dialog_send_viewport2), dialog_send_table2);

  src_checkbutton = NULL;
  for (Cnt = 0; Cnt < MAXCLIENT; Cnt++) {
    if (server_CB.client_grp[Cnt] == NULL) continue;
    recv_state_tmp[Cnt] = GETRECV(Cnt);
    send_state_tmp[Cnt] = GETSEND(Cnt);
    if (server_CB.user_num == ++user_cnt) break;
  }

  makeCombobox1_dialog_send();
  makeCombobox2_dialog_send();

  user_cnt = 0;
  dialog_send_table1 = makeTable_userList();
  for (pCnt = 0; pCnt < tab_num; pCnt++) {
    for (dCnt = 0; dCnt < TABGROUP_MAX; dCnt++) {
      if (draw_info[pCnt].client_num[dCnt] == EMPTY) continue;
      if (GETRECV(draw_info[pCnt].client_num[dCnt]) || (strcmp((char *)server_CB.client_grp[draw_info[pCnt].client_num[dCnt]]->client_ID, (char *)server_CB.server_ID) == 0)) {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[pCnt][dCnt]), TRUE);
	gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dialog_send_checkbutton2[pCnt][dCnt]), TRUE);
      } else
	g_signal_connect ((gpointer) dialog_send_checkbutton2[pCnt][dCnt], "toggled",
			  G_CALLBACK (on_dialog_send_checkbutton2_toggled),
			  (gpointer) ((pCnt << 8)+dCnt));
      if (server_CB.user_num == ++user_cnt) break;
    }
    g_signal_connect ((gpointer) dialog_send_checkbutton1[pCnt], "toggled",
		      G_CALLBACK (on_dialog_send_checkbutton1_toggled),
		      (gpointer) pCnt);
  }

  gtk_container_add (GTK_CONTAINER (dialog_send_viewport1), dialog_send_table1);
  gtk_widget_show (dialog_send_table1);

  dialog_send_table2 = makeTable_send_state();
  gtk_container_add (GTK_CONTAINER (dialog_send_viewport2), dialog_send_table2);
  gtk_widget_show (dialog_send_table2);
}


/*******************************************************************
 *ロック設定ダイアログで使用される関数
 *******************************************************************/

gboolean
on_dialog_lock_delete_event                (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_lock);
  gtk_widget_destroy(dialog_lock);

  return TRUE;
}


/*
  全体ロック用check buttonをクリックした時に呼び出される.
 */
void
on_dialog_lock_checkbutton0_toggled        (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
  int p, d, num;
  gboolean toggle_flag;

  toggle_flag = gtk_toggle_button_get_active(togglebutton);
  for (p = 0; p < tab_num; p++) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton1[p]), toggle_flag);
    for (d = 0; d < TABGROUP_MAX; d++) {
      if ((num = draw_info[p].client_num[d]) == EMPTY) continue;
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), toggle_flag);
    }
  }
}


void
on_dialog_lock_buttonOK_clicked            (GtkButton       *button,
                                        gpointer         user_data)
{
  locking_start();

  gtk_grab_remove(dialog_lock);
  gtk_widget_destroy(dialog_lock);
}


void
on_dialog_lock_buttonCancel_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_lock);
  gtk_widget_destroy(dialog_lock);
}


void
on_dialog_lock_buttonApply_clicked         (GtkButton       *button,
                                        gpointer         user_data)
{
  locking_start();
}


/*
  グループロック用check buttonをクリックした時に呼び出される.
 */
void on_dialog_lock_checkbutton1_toggled                (GtkToggleButton *togglebutton,
		                                     gpointer         user_data)
{
  int p = (int)user_data;
  int d;
  gboolean toggle_flag;

  toggle_flag = gtk_toggle_button_get_active(togglebutton);
  for (d = 0; d < TABGROUP_MAX; d++) {
    if (draw_info[p].client_num[d] == EMPTY) continue;
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]), toggle_flag);
  }
}


/*
  個人ロック用check buttonをクリックした時に呼び出される.
 */
void on_dialog_lock_checkbutton2_toggled                (GtkToggleButton *togglebutton,
		                                     gpointer         user_data)
{

}


/*
  ダイアログの内容の通りにロックを行う関数.
 */
void locking_start(void)
{
  int p, d, num;
  gboolean lock_flag = FALSE;

  for (p = 0; p < tab_num; p++) {
    for (d = 0; d < TABGROUP_MAX; d++) {
      if ((num= draw_info[p].client_num[d]) == EMPTY) continue;
      if (strcmp((char *)server_CB.client_grp[num]->client_ID, (char *)server_CB.server_ID) == 0) continue;
      lock_flag = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog_send_checkbutton2[p][d]));
      if ((lock_flag && !GETLOCK(num)) || (!lock_flag && GETLOCK(num))) {
	SETLOCK(num, lock_flag);
	SendLockMsg(lock_flag, num);
      }
    }
  }
}


/*******************************************************************
 *MultiVNC終了確認ダイアログで使用される関数
 *******************************************************************/

gboolean
on_dialog_quit_delete_event            (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_quit);
  gtk_grab_remove(dialog_quit);

  return TRUE;
}


void
on_dialog_quit_buttonOK_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_quit);
  gtk_grab_remove(dialog_quit);

  Cleanup();
  exit(0);
}


void
on_dialog_quit_buttonCancel_clicked    (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_quit);
  gtk_grab_remove(dialog_quit);
}


/*******************************************************************
 *バージョン情報表示ダイアログで使用される関数
 *******************************************************************/

gboolean
on_dialog_version_delete_event         (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_version);
  gtk_grab_remove(dialog_version);

  return TRUE;
}


void
on_dialog_version_buttonOK_clicked     (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_version);
  gtk_grab_remove(dialog_version);
}


void
on_dialog_send_fullscreen_radiobutton_toggled
                                        (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
  fullscreen_flag = 1;
}


void
on_dialog_send_window_radiobutton_toggled
                                        (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
  fullscreen_flag = 0;
}


/*******************************************************************
 *通知ダイアログで使用される関数
 *******************************************************************/

gboolean
on_dialog_notice_delete_event          (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_notice);
//  gtk_main_quit();
  return TRUE;
}


void
on_dialog_notify_okbutton_clicked      (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_notice);
//  gtk_main_quit();
}


