/*
 * dipcx.c
 *
 * A graphical tool to manage DIPC in a computer. Requires xview.
 * Part of dipcx program.
 *
 * By Kamran Karimi
 */

#include <xview/xview.h>
#include <xview/frame.h>
#include <xview/panel.h>
#include <xview/notice.h>
#include <xview/openmenu.h>

#include "dipcx.h"

Frame frame;
Panel panel, panel_list;
Panel config_panel;
Panel shm_panel;

int display_struct = 0;
int display_config = 0;
int display_shm = 0;

int struct_select;
int show_struct;

Panel_item remove_struct, info_struct, manager_struct;

void show_ok_notice(char *message)
{
 notice_prompt(panel, NULL,
  NOTICE_MESSAGE_STRINGS, message, NULL,
  NOTICE_BUTTON_YES, "Ok",
  NULL);
}

void show_ok_2_notice(char *message, char *message2)
{
 notice_prompt(panel, NULL,
  NOTICE_MESSAGE_STRINGS, message, message2, NULL,
  NOTICE_BUTTON_YES, "Ok",
  NULL);
}

void show_ok_3_notice(char *message, char *message2, char *message3)
{
 notice_prompt(panel, NULL,
  NOTICE_MESSAGE_STRINGS, message, message2, message3, NULL,
  NOTICE_BUTTON_YES, "Ok",
  NULL);
}

void show_ok_4_notice(char *mess, char *mess2, char *mess3, char *mess4)
{
 notice_prompt(panel, NULL,
  NOTICE_MESSAGE_STRINGS, mess, mess2, mess3, mess4, NULL,
  NOTICE_BUTTON_YES, "Ok",
  NULL);
}

void program_about(void)
{
 char buff[80];
 
 sprintf(buff,"%s: A management program for DIPC", PRG_NAME);
 show_ok_4_notice(buff, "(Distributed Inter-Process Communication)", " ", 
 "By Kamran Karimi");
}


int show_help(char **help, int idx, int total)
{
 return notice_prompt(panel, NULL,
   NOTICE_MESSAGE_STRINGS, help[idx], help[idx + 1], 
   help[idx + 2], help[idx + 3], help[idx + 4], NULL,
   NOTICE_BUTTON_NO, "Done",
   NOTICE_BUTTON_YES, (((total - 1) * 5 == idx) ? "Done" : "Next"),
   NULL);
}   


void program_help(void)
{
 int count;

 if(display_struct == 1)
 {
  if(show_struct == KERNEL)
  {
   char *help[10] = 
   {
    "You are now seeing some information about the ",
    "IPC strucures that are inside the kernel of   ",
    "this computer. The first column shows the type",
    "of the structure. The next one shows its key. ",
    "If the entry is a Shared Memory, you may get  ",
    "more information about it by clicking on the  ",
    "Manager button. This succeeds only if the     ",
    "manager is running in this computer           ", 
    "",
    ""
   };
   for(count = 0; count < 2; count++)
   {
    if(show_help(help, count * 5, 2) == NOTICE_NO) 
     break;
   }
  }
  else if(show_struct == REFEREE)
  {
   char *help[5] = 
   {
    "You are now seeing some information about the     ",
    "IPC structures that are registered in the Referee ",
    "of this DIPC cluster. The first column shows the  ",
    "type of the structure. The next one shows its key.",
    ""
   };
   for(count = 0; count < 1; count++)
   {
    if(show_help(help, count * 5, 1) == NOTICE_NO) 
     break;
   }
  }   
 }
 else if(display_config == 1)
 {
  char *help[10] =
  {
   "If the DIPC configuration file exists and is readable ",
   "then you are now seeing its contents, otherwise some  ",
   "default information is displayed. Change them to suite",
   "your configuration, and then save them. Note that the ",
   "changes won't have any effect until the dipcd program ",
   "is restarted.                                         ",
   "",
   "Set This computer's address to 'dipc_auto_find', to   ",
   "cause its IP address to be determined by dipcd after  ",
   "start up.                                             "
  };
  for(count = 0; count < 2; count++)
  {
   if(show_help(help, count * 5, 2) == NOTICE_NO) 
    break;
  }
 }
 else if(display_shm == 1)
 {
  char *help[10] = 
  {
   "You are now seeing some information about the     ",
   "usage of a shared memory. The first column shows  ",
   "the page number. If DIPC is configured to use     ",
   "segments, then page 0 means the whole shared      ",
   "memory. The next column shows the state of access ",
   "request. Column three shows the kind of access    ",
   "(read or write). The last column shows the network",
   "address of the requesting computer                ",
   "",
   ""
  };
  for(count = 0; count < 2; count++)
  {
   if(show_help(help, count * 5, 2) == NOTICE_NO) 
    break;
  }
 }
 else
 {
  char *help[25] = 
  {
   "This program is used to help people view or  ",
   "manipulate (D)IPC structures in the kernel or",
   "the Referee process. It can also be used for ",
   "configuring DIPC in this computer.           ",
   "",   
   "Choose Structures/Kernel to see the list of kernel ",
   "structures. If the Referee of the DIPC cluster runs",
   "in this computer, then Structures/Referee displays ",
   "the structures in this process.                    ",
   "",
   "While viewing the structures, Use the Info button",
   "to see more information about the selected one.  ",
   "The Remove button tries to remove the structue.  ",
   "",   
   "When viewing a shared memory structure in the    ", 
   "kernel you may get some information about its    ",
   "usage by clicking the Manager button. This       ",
   "succeeds only if the manager is running in this  ",
   "computer.                                        ", 
   "",   
   "To update the information at any time, just select",
   "the menu again.                                   ",
   "",   
   "You could view and changes the DIPC configuration",
   "file by selecting the Config button              "
  };
  for(count = 0; count < 5; count++)
  {
   if(show_help(help, count * 5, 5) == NOTICE_NO) 
    break;
  } 
 }
} 

int struct_show(Panel_item item, Event *event)
{
/* printf("%s selected\n", (char *)xv_get(item, PANEL_LABEL_STRING)); */
 return XV_OK;
}

void shm_proc(void)
{
 get_shm_list(shm_key(struct_select));
}

void which_entry(Panel_item item, char *string, caddr_t client_data,
                                         Panel_list_op op, Event *event)
{
 /* printf("item: %d\n", (int) client_data); */
 struct_select = (int) client_data;
 if((op == PANEL_LIST_OP_SELECT) && (show_struct == KERNEL) && 
                                             is_shm((int)client_data))
  xv_set(manager_struct, PANEL_INACTIVE, FALSE, NULL);
 else if(op == PANEL_LIST_OP_SELECT)
  xv_set(manager_struct, PANEL_INACTIVE, TRUE, NULL); 
}                                         

void clean_struct(void)
{
 if(display_struct == 1)
 {
  xv_destroy(panel_list);
  display_struct = 0;
  struct_select = NONE;
 }
}

void clean_config(void)
{
 if(display_config == 1)
 {
  xv_destroy(config_panel); 
  display_config = 0;
 } 
} 

void clean_shm(void)
{
 if(display_shm == 1)
 {
  xv_destroy(shm_panel); 
  display_shm = 0;
 } 
} 

void clean_all(void)
{
 clean_config();
 clean_struct();
 clean_shm();
 xv_set(manager_struct, PANEL_INACTIVE, TRUE, NULL);
 xv_set(remove_struct, PANEL_INACTIVE, TRUE, NULL);
 xv_set(info_struct, PANEL_INACTIVE, TRUE, NULL);  
 window_fit(panel);
 window_fit(frame);
}

static void struct_menu(char *menutext);

void remove_struct_proc(void)
{
 if(show_struct == KERNEL)
 { 
  rem_kernel_info(struct_select);
  struct_menu("Kernel");
 }
 else if(show_struct == REFEREE)
 {
  rem_referee_info(struct_select);
  struct_menu("Referee");
 } 
}

void info_struct_proc(void)
{
 if(show_struct == KERNEL) 
  get_kernel_info(struct_select);
 else if(show_struct == REFEREE)
  get_referee_info(struct_select);
}


static void struct_menu(char *menutext)
{
 int num_entries;

 clean_all(); 
 
 display_struct = 1;
 
 xv_set(panel, PANEL_LAYOUT, PANEL_VERTICAL, NULL);
 panel_list = xv_create(panel, PANEL_LIST,
         PANEL_LIST_DISPLAY_ROWS, 10,
         PANEL_READ_ONLY, TRUE,
         PANEL_LIST_STRINGS, NULL,
         PANEL_LIST_CLIENT_DATAS, NULL,
         PANEL_NOTIFY_PROC, which_entry,
         NULL);

 struct_select = 0;
 
 if(!strcmp(menutext, "Kernel"))
 {
  show_struct = KERNEL;
  num_entries = get_kernel_list();
 } 
 else if(!strcmp(menutext, "Referee"))
 {
  show_struct = REFEREE;
  num_entries = get_referee_list();
 } 

 window_fit(panel);
 window_fit(frame);  

 if(num_entries == -1)
 {
  clean_all();
  show_ok_notice("No Structure was found");
 }
 else
 {
  xv_set(info_struct, PANEL_INACTIVE, FALSE, NULL);
  xv_set(remove_struct, PANEL_INACTIVE, FALSE, NULL);
 }  
 if((num_entries != -1 ) && (show_struct == KERNEL) && is_shm(0))
  xv_set(manager_struct, PANEL_INACTIVE, FALSE, NULL);  

 window_fit(panel);
 window_fit(frame);
}


void struct_menu_proc(Menu menu, Menu_item menu_item)
{
 struct_menu((char *) xv_get(menu_item, MENU_STRING));
}

void main(int argc, char **argv)
{
 Menu struct_menu;
 
 xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
 
 frame = (Frame) xv_create(NULL, FRAME, 
               FRAME_LABEL, PRG_NAME,
               NULL);
                              
 panel = (Panel) xv_create(frame, PANEL, NULL);
         
 struct_menu = (Menu) xv_create(NULL, MENU,
         MENU_NOTIFY_PROC, struct_menu_proc,
         MENU_STRINGS, "Kernel", "Referee", NULL,
         NULL);
         
 (void) xv_create(panel, PANEL_BUTTON,
         PANEL_LABEL_STRING, "Structures",
         PANEL_NOTIFY_PROC, struct_show,
         PANEL_ITEM_MENU, struct_menu,
         NULL);
 
  manager_struct = xv_create(panel, PANEL_BUTTON,
                    PANEL_LABEL_STRING, "Manager",
                    PANEL_INACTIVE, TRUE,
                    PANEL_NOTIFY_PROC, shm_proc,
                    NULL);        

 (void) xv_create(panel, PANEL_BUTTON,
         PANEL_LABEL_STRING, "Config",
         PANEL_NOTIFY_PROC, dipc_config,
         NULL);        

 xv_set(panel, PANEL_LAYOUT, PANEL_VERTICAL, NULL);

 remove_struct = xv_create(panel, PANEL_BUTTON,
                  PANEL_LABEL_STRING, "Remove",
                  PANEL_NOTIFY_PROC, remove_struct_proc,
                  PANEL_INACTIVE, TRUE,
                  NULL);        
                  
 xv_set(panel, PANEL_LAYOUT, PANEL_HORIZONTAL, NULL); 
 
 info_struct = xv_create(panel, PANEL_BUTTON,
                  PANEL_LABEL_STRING, "Info",
                  PANEL_NOTIFY_PROC, info_struct_proc,
                  PANEL_INACTIVE, TRUE,
                  NULL);        

 (void) xv_create(panel, PANEL_BUTTON,
         PANEL_LABEL_STRING, "Help",
         PANEL_NOTIFY_PROC, program_help,
         NULL);        


 (void) xv_create(panel, PANEL_BUTTON,
         PANEL_LABEL_STRING, "About",
         PANEL_NOTIFY_PROC, program_about,
         NULL);        

 window_fit(panel);
 window_fit(frame);                 
 xv_main_loop(frame);
 exit(0);
}
