/* truly_misc.c
 * Written by David Allen
 * s2mdalle@titan.vcu.edu
 * http://opop.nols.com/
 *
 * This is the place for all the things I couldn't figure out where to put. :)
 * Although it will probably get subcategorized Real Soon Now
 * Thanks to the GTK tutorial for this function xpm_to_widget (modified)
 */
/* GTKeyboard - A Graphical Keyboard For X
 * Copyright (C) 1999, 2000 David Allen  
 *
 * 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 Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */

#define TRULY_MISC_C
#include "master.h"
#include "xpm/splash.h"

void HideAllButKeyboard(GtkWidget *emitter, gint input)
{
     hide_widget(NOWIDGET, HIDE_OUTPUT);
     hide_widget(NOWIDGET, HIDE_BOTTOM_ROW_BUTTONS);
     hide_widget(NOWIDGET, HIDE_TOOLBAR);
     hide_widget(NOWIDGET, HIDE_STATUS);
     hide_widget(NOWIDGET, HIDE_OUTPUT);

     update_menus();
} /* End HideAllButKeyboard() */

void ShowAll(GtkWidget *emitter, gint input)
{
     /* Show the output text box */
     unhide_widget(NOWIDGET, SHOW_OUTPUT);
     /* Show the bottom row of buttons */
     unhide_widget(NOWIDGET, SHOW_BOTTOM_ROW_BUTTONS);
     /* Show the toolbar */
     unhide_widget(NOWIDGET, SHOW_TOOLBAR);
     /* Show the status widget */
     unhide_widget(NOWIDGET, SHOW_STATUS);
     /* Show the text output */
     unhide_widget(NOWIDGET, SHOW_OUTPUT);

     unhide_widget(NOWIDGET, SHOW_MENUS);
     unhide_widget(NOWIDGET, SHOW_KEYBOARD);

     /* Reset the keyboard attribute flags so we can show
      * everything in the keyboard.
      */
     GUI.keyboard_elements.show_keyboard    = ON;
     GUI.keyboard_elements.show_cursor_keys = ON;
     GUI.keyboard_elements.show_f_keys      = ON;
     GUI.keyboard_elements.show_number_pad  = ON;

     /* Re-show ALL keyboard elements */
     do_keyboard_sublayout();
     update_menus();
} /* End ShowAll() */

/* Hides various screen widgets */
void hide_widget(GtkWidget *emitter, gint input)
{
/* Quick macro to only hide something if it is a valid widget, otherwise
 * issue an error message to the user.  (QHIDE = quick hide)
 * this macro is only used in this function.
 */
#define QHIDE(wid,var)    if(!wid || (wid && !GTK_IS_WIDGET(wid))) \
                          chocolate("Can't Hide/Show:  Uninitialized!\n"); \
                          else{ gtk_widget_hide(wid); var = OFF; } break;

     switch(input)
     {
     case HIDE_KBD_KBD:        QHIDE(GUI.keyboard_elements.keyboard,
				     GUI.keyboard_elements.show_keyboard);
     case HIDE_KBD_CURSOR_PAD: QHIDE(GUI.keyboard_elements.cursor_keys,
				     GUI.keyboard_elements.show_cursor_keys);
     case HIDE_KBD_FKEYS:      QHIDE(GUI.keyboard_elements.f_keys,
				     GUI.keyboard_elements.show_f_keys);
     case HIDE_KBD_NUMBERPAD:  QHIDE(GUI.keyboard_elements.number_pad,
				     GUI.keyboard_elements.show_number_pad);
		    
     case HIDE_OUTPUT:
	  ELEMENTS.text = OFF;
	  gtk_widget_hide(GUI.master_text);
	  break;
     case HIDE_BOTTOM_ROW_BUTTONS:
	  ELEMENTS.buttonbar = OFF;
	  gtk_widget_hide(GUI.bottom_row_buttons);
	  break;
     case HIDE_MENUS:
	  gtk_widget_hide(GUI.menubar);
	  options.SHOW_MENU = OFF;
	  ELEMENTS.menubar = OFF;
	  /* make_item_factory(); */
	  break;
     case HIDE_TOOLBAR:
	  ELEMENTS.toolbar = OFF;
	  gtk_widget_hide(GUI.toolbar);  /* Hide the toolbar */
	  break;
     case HIDE_STATUS:
	  ELEMENTS.status = OFF;
	  gtk_widget_hide(GUI.s_table); /* Hide the status window */
	  break;
     case HIDE_KEYBOARD:
	  ELEMENTS.keyboard = OFF;
	  gtk_widget_hide(GUI.KEYBOARD); /* Hide the keyboard */
	  break;
     default:
          fprintf(Q,"hide_widget: got unknown switch %d\n",input);
          fflush(Q);
	  break;
     } /* End switch */

     /* This call updates the check items in the menu to reflect current
      * status 
      */
     update_menus();
} /* End hide_widget */

/* Shows various widgets */
void unhide_widget(GtkWidget *emitter, gint input)
{
/* Quick macro to only show a valid widget
 * QSHOW = quick show.
 * If it isn't a valid widget, spit out an error message, otherwise,
 * show the widget
 * This macro is only used in this function
 */
#define QSHOW(wid,var)    if(!wid || (wid && !GTK_IS_WIDGET(wid)))\
                          chocolate("Cannot Hide/Show: Uninitialized!\n");\
                          else{ gtk_widget_show_all(wid); var = ON; } break;
     switch(input)
     {
     case SHOW_KBD_KBD:        QSHOW(GUI.keyboard_elements.keyboard,
				     GUI.keyboard_elements.show_keyboard);
     case SHOW_KBD_CURSOR_PAD: QSHOW(GUI.keyboard_elements.cursor_keys,
				     GUI.keyboard_elements.show_cursor_keys);
     case SHOW_KBD_FKEYS:      QSHOW(GUI.keyboard_elements.f_keys,
				     GUI.keyboard_elements.show_f_keys);
     case SHOW_KBD_NUMBERPAD:  QSHOW(GUI.keyboard_elements.number_pad,
				     GUI.keyboard_elements.show_number_pad);

     case SHOW_OUTPUT:
	  ELEMENTS.text = ON;
	  gtk_widget_show_all(GUI.master_text);
	  break;
     case SHOW_TOOLBAR:
	  ELEMENTS.toolbar = ON;
	  gtk_widget_show_all(GUI.toolbar);
	  break;
     case SHOW_MENUS:
	  gtk_widget_show_all(GUI.menubar);
	  ELEMENTS.menubar = ON;
	  options.SHOW_MENU = ON;
	  /* make_item_factory(); */
	  break;
     case SHOW_BOTTOM_ROW_BUTTONS:
	  ELEMENTS.buttonbar = ON;
	  gtk_widget_show_all(GUI.bottom_row_buttons);
	  break;
     case SHOW_STATUS:
	  ELEMENTS.status = ON;
	  gtk_widget_show_all(GUI.s_table);  /* Show the status menu table */
	  break;
     case SHOW_KEYBOARD:
	  ELEMENTS.keyboard = ON;
	  gtk_widget_show(GUI.KEYBOARD);
	  break;
     default:
          fprintf(Q,"unhide_widget: got unknown switch %d\n",input);
          fflush(Q);
	  break;
     } /* End switch */

     /* This call updates the check items in the menu to reflect current
      * status 
      */
     update_menus();
} /* End unhide_widget */

GtkWidget *xpm_to_widget(GtkWidget *foo, gchar **xpm_data)
{
     /* GtkWidget is the storage type for widgets */
     GtkWidget *pixmapwid;
     GdkPixmap *pixmap;
     GdkBitmap *mask;
     GtkStyle *style;

     style = gtk_widget_get_style(window);

     /* In order for this to not create a warning, window has to be a
      * gtk_realize_widget (realized) widget
      */
     pixmap = gdk_pixmap_create_from_xpm_d(window->window,  &mask,
					   &style->bg[GTK_STATE_NORMAL],
					   (gchar **)xpm_data );
 
     /* a pixmap widget to contain the pixmap */
     pixmapwid = gtk_pixmap_new(pixmap, mask);
     gtk_widget_show(pixmapwid);
     
     return(pixmapwid);
} /* End xpm_to_widget */

GtkWidget *widget_from_xpm_file(const char *filename)
{
     GdkPixmap *pixmap;
     GdkBitmap *bitmap;
     GtkWidget *widget;

     pixmap = gdk_pixmap_create_from_xpm(window->window, &bitmap, 
					 (GdkColor *)NULL, filename);
     widget = gtk_pixmap_new(pixmap, bitmap);
     return(widget);
} /* End widget_from_xpm_file */

void splash(GtkWidget *emitter, gpointer data)
{
     GtkWidget *window, *button;
     GtkWidget *foo = (GtkWidget *)NULL;
     
     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

     /* Give the xpm a small border */
     gtk_widget_set_usize(window, 310, 119);

     gtk_window_set_title(GTK_WINDOW(window), "GTKeyboard");

     gtk_signal_connect(GTK_OBJECT(window), "delete_event",
			GTK_SIGNAL_FUNC(gtk_widget_destroy), window);

     foo = xpm_to_widget(window, (gchar **)splash_xpm);

     button = gtk_button_new();
     gtk_container_add(GTK_CONTAINER(button), foo);
     gtk_signal_connect(GTK_OBJECT(button), "clicked",
			GTK_SIGNAL_FUNC(smack), window);

     gtk_container_add(GTK_CONTAINER(window), button);
     
     gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

     gtkeyboard_window_common_setup(window);
     gtk_widget_show_all(window);
} /* End splash */

gint final_check(void)
{
     /* Make a dialog instead of homegrown */
     GtkWidget *finalcheck;
     GtkWidget *yes, *no, *label;

     finalcheck = gtk_dialog_new();
     yes = create_ok_button(GTK_SIGNAL_FUNC(CloseApp), finalcheck);
     no  = create_cancel_button(finalcheck);
     label = gtk_label_new("Are you sure you want to quit?");

     /* Pack them into the dialog box */
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(finalcheck)->vbox),
			label, TRUE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(finalcheck)->action_area),
			yes, TRUE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(finalcheck)->action_area),
			no, TRUE, TRUE, 0);

     gtk_window_set_position(GTK_WINDOW(finalcheck), GTK_WIN_POS_CENTER);
     
     gtkeyboard_window_common_setup(finalcheck);
     gtk_widget_show_all(finalcheck);
     return(TRUE);
} /* End final_check */

void grab_a_window(GtkWidget *w, gpointer data)
{
     int frame = 0;

     redirect_to = Select_Window_Args(fargc, fargv);

     /* Set other back to null so we have to look for another window before
      * we insert keys into that window 
      */
     options.other = (Window)NULL;

     chocolate("\n\nCHOOSE THE WINDOW TO REDIRECT TO WITH THE POINTER\n\n");

     /* Get the user to use the pointer to select a window */
     redirect_to = Select_Window(GDK_DISPLAY());

     if (redirect_to && !frame)
     {
	  Window root;
	  int dummyi;
	  unsigned int dummy;

	  if (XGetGeometry(GDK_DISPLAY(), redirect_to, &root, &dummyi, &dummyi,
			    &dummy, &dummy, &dummy, &dummy) && 
	      redirect_to != root)
	  {
	       redirect_to = XmuClientWindow(GDK_DISPLAY(), redirect_to);
	  } /* End if */
     } /* End if */

     /* Display_window_id will automatically reallocate 
      * options.redirect_window_name  and so on.
      */
     (void *)Display_Window_Id(redirect_to, True);
     
     options.redirect_window = 
          RootWindow(GDK_DISPLAY(),DefaultScreen(GDK_DISPLAY()));
     
     /* Everything should be set up */

     /* Note:  If they chose an invalid window name, then
      * options.redirect_window_name will be NULL and chocolate will 
      * cause a segfault if given that.  (gtk_text_insert problem?)
      */

     if(options.redirect_window_name)
     {
          options.other = find_window(options.redirect_window,
			    	      options.redirect_window_name);

	  /* Valid window name */
	  gtkeyboard_message(3,"Ok, now we've got \"",
			     options.redirect_window_name,
			     "\" as the window we're pointing at.\n");
     } /* End if */
     else
     {
	  /* Invalid window.  Make the user keep picking till he gets
	   * something we can address.
	   */
	  gtkeyboard_error(3,"\nI'm sorry, but that window has no name.\n",
			   "Did you choose the root window to redirect to?\n",
			   "OUTPUT WINDOW NOT CHOSEN-PLEASE CHOOSE AGAIN\n\n");
#ifdef ANNOYING_INFORMATION_POPUPS
	  annoying_popup("Error:  Window not chosen - see status.");
#endif /* ANNOYING_INFORMATION_POPUPS */			   

     } /* End else */
     return;
} /* End grab_a_window */

void send_redirect_a_keysym(KeySym input)
{
     Window window;
     int revert_to;

     if(!options.other || options.other == (Window)NULL)
     {
	  /* SEND_TO_BOTH_WINDOWS was probably set and there wasn't
	   * a redirect window to send to.  Let's save the time involved
	   * with doing all this string crap and just jump out here.
	   */
	  return;
     } /* End if */

     if(options.other)
     {
         /* send to window user picked */
	 keysym_sendkey(input, options.other);
     } /* End if */
     else
     {
	  /* default to just send the event to whatever window has the input
	   * focus 
	   */
	  chocolate("WARNING: Getting input focus and sending it there.\n");
	  XGetInputFocus (GDK_DISPLAY(), &window, &revert_to);
	  keysym_sendkey(input, window);
     } /* End else */
} /* End send_redirect_a_keysym() */

void ignore_window(void)
{
     if(options.redirect_window_name)
     {
	  chocolate("Ignoring old window ");
	  chocolate(options.redirect_window_name);
	  chocolate("\n");
	  g_free_(options.redirect_window_name);
	  options.redirect_window_name = NULL;
     } /* End if */
     else
     {
	  gtkeyboard_error(1, "No redirect window to ignore.\n");
     } /* End else */

     options.other = (Window)NULL;
     options.redirect_window_name = NULL;  /* Gets nullified for later tests */
} /* End ignore_window */
