Logo Search packages:      
Sourcecode: x2 version File versions

callbacks.c

static GtkWidget *New( GtkWidget *widget, GtkWidget *notebook )
{
      // Create node instance
      struct node *doc = g_malloc( sizeof( struct node ) );
      doc->Box = gtk_vbox_new( FALSE, 0 );
      doc->Name = "Untitled";
      doc->Location = "None";
      doc->Scroller = gtk_scrolled_window_new( NULL, NULL );
      #ifdef G_OS_UNIX  
      doc->Buffer = gtk_source_buffer_new( NULL );
      doc->Doc = gtk_source_view_new_with_buffer( GTK_SOURCE_BUFFER( doc->Buffer ) );
      doc->Term = vte_terminal_new( );
      doc->TermScroll = gtk_scrolled_window_new( NULL, NULL );
      #endif      
      #ifndef G_OS_UNIX
      doc->Buffer = gtk_text_buffer_new( NULL );
      doc->Doc = gtk_text_view_new_with_buffer( GTK_TEXT_BUFFER( doc->Buffer ) );
      #endif
      doc->Label = gtk_label_new( doc->Name );
      doc->TabBox = gtk_hbox_new( FALSE, 0 );
      doc->Image = gtk_image_new_from_stock( GTK_STOCK_CLOSE, GTK_ICON_SIZE_SMALL_TOOLBAR );
      doc->Button = gtk_button_new( );
      doc->SearchBox = gtk_hbox_new( FALSE, 0 );
      doc->Search1 = gtk_entry_new( );
      doc->ReplaceBox = gtk_vbox_new( FALSE, 0 );
      doc->Search2 = gtk_entry_new( );
      doc->Replace2 = gtk_entry_new( );
      doc->Searchlbl1 = gtk_label_new( "Search: " );
      doc->Searchlbl2 = gtk_label_new( "Search: " );
      doc->Replacelbl = gtk_label_new( "Replace: " );
      doc->Paned = gtk_vpaned_new( );
      doc->Frame = gtk_frame_new( NULL );
      doc->JumpLbl = gtk_label_new( "Jump to line: " );
      doc->JumpSpin = gtk_spin_button_new_with_range( 1, 1, 1 );
      doc->JumpBox = gtk_hbox_new( FALSE, 0 );
      gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", doc->Name, NULL ) );

      // Pango-font stuff
      PangoFontDescription *PFD = pango_font_description_from_string( sets->font );
      gtk_widget_modify_font( doc->Doc, PFD );

      // Create stuff instance
      struct str_data *tmp = g_malloc( sizeof( struct str_data ) );
      tmp->Widget = GTK_WIDGET( doc->Paned );
      tmp->Notebook = notebook;
      
      // Entry widgets icons
      gtk_entry_set_icon_from_stock( GTK_ENTRY( doc->Search1 ), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_FIND );
      gtk_entry_set_icon_from_stock( GTK_ENTRY( doc->Search2 ), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_FIND );
      gtk_entry_set_icon_from_stock( GTK_ENTRY( doc->Replace2 ), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_FIND_AND_REPLACE );
      gtk_entry_set_icon_from_stock( GTK_ENTRY( doc->JumpSpin ), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_JUMP_TO );
      gtk_entry_set_width_chars( GTK_ENTRY( doc->JumpSpin ), 5 );
      
      // Set button properties
      gtk_button_set_image( GTK_BUTTON( doc->Button ), doc->Image );
      gtk_widget_set_tooltip_text( GTK_WIDGET( doc->Button ), "Close document" );

      // Extra boxes
      GtkWidget *hb1 = gtk_hbox_new( FALSE, 0 );
      GtkWidget *hb2 = gtk_hbox_new( FALSE, 0 );

      // Add/pack widgets
      gtk_container_add( GTK_CONTAINER( doc->Scroller ), doc->Doc );
      gtk_container_add( GTK_CONTAINER( doc->Frame ), doc->Scroller );
      
      gtk_box_pack_end( GTK_BOX( doc->SearchBox ), doc->Search1, FALSE, FALSE, 0 );
      gtk_box_pack_end( GTK_BOX( doc->SearchBox ), doc->Searchlbl1, FALSE, FALSE, 0 );
      
      gtk_box_pack_end( GTK_BOX( hb2 ), doc->Replace2, FALSE, FALSE, 0 );
      gtk_box_pack_end( GTK_BOX( hb2 ), doc->Replacelbl, FALSE, FALSE, 0 );
      gtk_box_pack_end( GTK_BOX( hb1 ), doc->Search2, FALSE, FALSE, 0 );
      gtk_box_pack_end( GTK_BOX( hb1 ), doc->Searchlbl2, FALSE, FALSE, 0 );   
      
      gtk_box_pack_start( GTK_BOX( doc->ReplaceBox ), hb1, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( doc->ReplaceBox ), hb2, FALSE, FALSE, 0 );

      gtk_box_pack_start( GTK_BOX( doc->TabBox ), doc->Label, FALSE, TRUE, 0 );
      gtk_box_pack_start( GTK_BOX( doc->TabBox ), doc->Button, FALSE, TRUE, 0 );
      
      gtk_box_pack_end( GTK_BOX( doc->JumpBox ), doc->JumpSpin, FALSE, FALSE, 0 );
      gtk_box_pack_end( GTK_BOX( doc->JumpBox ), doc->JumpLbl, FALSE, FALSE, 0 );
      
      gtk_box_pack_start( GTK_BOX( doc->Box ), doc->Frame, TRUE, TRUE, 0 );
      gtk_box_pack_start( GTK_BOX( doc->Box ), doc->SearchBox, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( doc->Box ), doc->ReplaceBox, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( doc->Box ), doc->JumpBox, FALSE, FALSE, 0 );

      // Set properties
      gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( doc->Scroller ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
      gtk_widget_queue_draw( GTK_WIDGET( notebook ) );
      gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), doc->Paned, doc->TabBox );
      gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( doc->TermScroll ), doc->Term );
      gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( doc->TermScroll ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );   
      gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( doc->Buffer ), FALSE );
      gtk_drag_dest_set( doc->Doc, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT, targets, n_targets, GDK_ACTION_COPY );

      // Experimental sourceview stuff
      if( g_strrstr( sets->highlightline, ":true" ) )
            gtk_source_view_set_highlight_current_line( GTK_SOURCE_VIEW( doc->Doc ), TRUE );
      
      // Sourceview prefs
      if( g_strrstr( sets->lines, ":true" ) )
            gtk_source_view_set_show_line_numbers( GTK_SOURCE_VIEW( doc->Doc ), TRUE );

      // Paned stuff
      gtk_paned_add1( GTK_PANED( doc->Paned ), doc->Box );
      
      // Vte stuff
      #ifdef G_OS_UNIX
      vte_terminal_set_background_transparent( VTE_TERMINAL( doc->Term ), TRUE );
      vte_terminal_set_size( VTE_TERMINAL( doc->Term ), 79, 2 );
      vte_terminal_set_scroll_on_output( VTE_TERMINAL( doc->Term ), TRUE );
      vte_terminal_set_scroll_on_keystroke( VTE_TERMINAL( doc->Term ), TRUE );
      gtk_paned_add2( GTK_PANED( doc->Paned ), doc->TermScroll );
      long size = pathconf( ".", _PC_PATH_MAX );
      char *buf, *ptr;

        if ( ( buf = ( char * ) g_malloc( ( size_t ) size ) ) != NULL ) 
            ptr = getcwd( buf, ( size_t ) size );

        vte_terminal_fork_command( VTE_TERMINAL( doc->Term ), NULL, NULL, NULL, ptr, TRUE, TRUE, TRUE );
      #endif
      
      gtk_paned_set_position( GTK_PANED( doc->Paned ), 450 );
      gtk_notebook_set_tab_reorderable( GTK_NOTEBOOK( notebook ), doc->Paned, TRUE );
      
      struct search_data *find1 = g_malloc( sizeof( struct search_data ) );
      find1->tmp = doc;
      find1->textmark = "search1";
      find1->Notebook = notebook;
      find1->Search = doc->Search1;

      struct search_data *find2 = g_malloc( sizeof( struct search_data ) );
      find2->tmp = doc;
      find2->textmark = "search2";
      find2->Notebook = notebook;
      find2->Search = doc->Search2;
      
      // Entry icon signals
      g_signal_connect( doc->Search1, "icon-press", G_CALLBACK( S1 ), find1 );
      g_signal_connect( doc->Search1, "activate", G_CALLBACK( S2 ), find1 );
      g_signal_connect( doc->Search2, "icon-press", G_CALLBACK( S1 ), find2 );
      g_signal_connect( doc->Search2, "activate", G_CALLBACK( S2 ), find2 );
      g_signal_connect( doc->Replace2, "icon-press", G_CALLBACK( C1 ), find2 );
      g_signal_connect( doc->Replace2, "activate", G_CALLBACK( C2 ), find2 );
      g_signal_connect( doc->JumpSpin, "icon-press", G_CALLBACK( G1 ), doc );
      g_signal_connect( doc->JumpSpin, "activate", G_CALLBACK( G2 ), doc );
      
      // Signals
      g_signal_connect( doc->Button, "clicked", G_CALLBACK( Close ), tmp );
      g_signal_connect( doc->Buffer, "changed", G_CALLBACK( BufferChanged ), doc );
      g_signal_connect( doc->Doc, "drag-data-received", G_CALLBACK( drag_data_received_handler ), notebook );

      // Show/hide widgets
      gtk_widget_show_all( doc->Paned );
      gtk_widget_show_all( doc->TabBox );
      gtk_widget_hide( doc->SearchBox );
      gtk_widget_hide( doc->ReplaceBox );
      #ifdef G_OS_UNIX
      gtk_widget_hide( doc->TermScroll );
      #endif
      gtk_widget_hide( doc->JumpBox );

      // Set new page
      gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), -1 );
      g_object_set_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document", doc );

      return( doc->Doc );
}

static void Open( GtkWidget *widget, GtkWidget *notebook )
{
      GtkWidget *OpenDialog = gtk_file_chooser_dialog_new( "Open file",
               NULL, 
               GTK_FILE_CHOOSER_ACTION_OPEN, 
               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
               GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
               NULL );

      // Add file filter support so X2 can't open video files etc 
      const gchar *f1 = "text/plain";
      GtkFileFilter *filter = gtk_file_filter_new( );
      gtk_file_filter_set_name( GTK_FILE_FILTER( filter ), "Text files" );
      gtk_file_filter_add_mime_type( GTK_FILE_FILTER( filter ), f1 );
      gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( OpenDialog ), filter );

      const gchar *home_dir = g_get_home_dir( );
      gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( OpenDialog ), home_dir );

      if( gtk_dialog_run( GTK_DIALOG( OpenDialog ) ) == GTK_RESPONSE_ACCEPT )
      {
            struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

            if( gtk_text_buffer_get_modified( GTK_TEXT_BUFFER( tmp->Buffer ) ) )
            {
                  New( NULL, notebook ); 
                  tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
            }     
            
            gchar *contents;

            tmp->Name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( OpenDialog ) );
            g_file_get_contents( tmp->Name, &contents, NULL, NULL );
            gtk_text_buffer_set_text( GTK_TEXT_BUFFER( tmp->Buffer ), contents, -1 );
            gtk_label_set_text( GTK_LABEL( tmp->Label ), g_strconcat( g_path_get_basename( tmp->Name ), " ", NULL ) );
            gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( tmp->Buffer ), FALSE );
            g_free( contents );
            
            highlight_code( tmp );

            if( tmp )   
                  gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", tmp->Name, NULL ) );
      }
      gtk_widget_destroy( OpenDialog );
}

static void SaveAs( GtkWidget *widget, GtkWidget *notebook )
{
      GtkWidget *SaveAsDialog = gtk_file_chooser_dialog_new( "Save file",
               NULL, 
               GTK_FILE_CHOOSER_ACTION_SAVE, 
               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
               GTK_STOCK_SAVE_AS, GTK_RESPONSE_ACCEPT,
               NULL );

      const gchar *home_dir = g_get_home_dir( );
      gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( SaveAsDialog ), home_dir );

      if( gtk_dialog_run( GTK_DIALOG( SaveAsDialog ) ) == GTK_RESPONSE_ACCEPT )
      {
            struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
            tmp->Name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( SaveAsDialog ) );

            write_file( tmp );
            gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( tmp->Buffer ), FALSE );
            gtk_label_set_text( GTK_LABEL( tmp->Label ), g_path_get_basename( tmp->Name ) );

            highlight_code( tmp );

            if( tmp )   
                  gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", tmp->Name, NULL ) );
      }
      gtk_widget_destroy( SaveAsDialog );
}

static void Save( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      gchar *name = "Untitled";

      if( tmp->Name == name )
            SaveAs( widget, notebook );
      
      else
            write_file( tmp );

      gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( tmp->Buffer ), FALSE );
      gtk_label_set_text( GTK_LABEL( tmp->Label ), g_path_get_basename( tmp->Name ) );
      
      highlight_code( tmp );

      if( tmp )   
            gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", tmp->Name, NULL ) );
}

static void Undo( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      if( gtk_source_buffer_can_undo( GTK_SOURCE_BUFFER( tmp->Buffer ) ) )
            gtk_source_buffer_undo( GTK_SOURCE_BUFFER( tmp->Buffer ) );
}

static void Redo( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      if( gtk_source_buffer_can_redo( GTK_SOURCE_BUFFER( tmp->Buffer ) ) )
            gtk_source_buffer_redo( GTK_SOURCE_BUFFER( tmp->Buffer ) );
}

static void Cut( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      if( gtk_text_buffer_get_has_selection( GTK_TEXT_BUFFER( tmp->Buffer ) ) )
      {
            GtkClipboard *clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
            gtk_text_buffer_cut_clipboard( GTK_TEXT_BUFFER( tmp->Buffer ), clipboard, TRUE );
      }
}

static void Copy( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      if( gtk_text_buffer_get_has_selection( GTK_TEXT_BUFFER( tmp->Buffer ) ) )
      {
            GtkClipboard *clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
            gtk_text_buffer_copy_clipboard( GTK_TEXT_BUFFER( tmp->Buffer ), clipboard );
      }
}

static void Paste( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      GtkClipboard *clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
      gtk_text_buffer_paste_clipboard( GTK_TEXT_BUFFER( tmp->Buffer ), clipboard, NULL, TRUE );
}

static void Find( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      
      if( gtk_widget_get_visible( tmp->SearchBox ) )
            gtk_widget_hide( tmp->SearchBox );
      else
      {
            gtk_widget_show_all( tmp->SearchBox );
            gtk_widget_hide( tmp->ReplaceBox );
            gtk_widget_hide( tmp->JumpBox );
            gtk_widget_grab_focus( tmp->Search1 );
      }
}

static void Replace( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      
      if( gtk_widget_get_visible( tmp->ReplaceBox ) )
            gtk_widget_hide( tmp->ReplaceBox );
      else
      {
            gtk_widget_show_all( tmp->ReplaceBox );
            gtk_widget_hide( tmp->SearchBox );
            gtk_widget_hide( tmp->JumpBox );
            gtk_widget_grab_focus( tmp->Search2 );
      }
}

static void Jump( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      if( gtk_widget_get_visible( tmp->JumpBox ) )
            gtk_widget_hide( tmp->JumpBox );
      else
      {
            gtk_widget_show_all( tmp->JumpBox );
            gtk_widget_hide( tmp->ReplaceBox );
            gtk_widget_hide( tmp->SearchBox );
            gtk_widget_grab_focus( tmp->JumpSpin );
      }
}

static void Cmd( GtkWidget *widget, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      
      if( gtk_widget_get_visible( tmp->TermScroll ) )
            gtk_widget_hide( tmp->TermScroll );
      else
            gtk_widget_show_all( tmp->TermScroll );
}

static void close_prefs( GtkWidget *widget, struct prefs *pref )
{
      if( gtk_widget_get_visible( GTK_WIDGET( pref->Prefs_Win ) ) )
            gtk_widget_destroy( GTK_WIDGET( pref->Prefs_Win ) );

      // Lock off!
      prefs_win_open = FALSE;
}

static void save_prefs( GtkWidget *widget, struct prefs *pref )
{
      GError *error = NULL;
      gchar *base = g_build_filename( g_get_home_dir( ), "/.config/X2/", NULL );
      gchar *fn = g_build_filename( base, "X2.conf", NULL );
      
      if( !g_file_test( fn, G_FILE_TEST_EXISTS ) )
            g_file_make_directory_with_parents( g_file_new_for_path( base ), FALSE, &error );

      // Get preference values
      gchar *programming_pref = "programmingfeatures:false\n";
      gchar *highlighting_pref = "syntaxhighlighting:false\n";    
      gchar *linenumbers_pref = "linenumbers:false\n";
      gchar *terminal_pref = "terminal:false\n";
      gchar *searchwords_pref = "searchinwords:false\n";
      gchar *searchcasesensitive_pref = "casesensitive:false\n";
      gchar *highlightline = "highlightline:false\n";
      const gchar *fontnamesize = gtk_font_button_get_font_name( GTK_FONT_BUTTON( pref->Font ) );

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->Programming_Check ) ) )
            programming_pref = "programmingfeatures:true\n";

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->Highlight_Check ) ) )
            highlighting_pref = "syntaxhighlighting:true\n";

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->Lines_Check ) ) )
            linenumbers_pref = "linenumbers:true\n";

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->Terminal_Check ) ) )
            terminal_pref = "terminal:true\n";

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->FindInWords ) ) )
            searchwords_pref = "searchinwords:true\n";

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->FindSensitive ) ) )
            searchcasesensitive_pref = "casesensitive:true\n";

      if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->HighlightLine ) ) )
            highlightline = "highlightline:true\n";

      gsize bytes;
      GIOChannel *write = g_io_channel_new_file( fn, "w", &error );
      g_io_channel_write_chars( write, programming_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, highlighting_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, linenumbers_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, terminal_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, searchwords_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, searchcasesensitive_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, highlightline, -1, &bytes, NULL );
      g_io_channel_write_chars( write, fontnamesize, -1, &bytes, NULL );
      g_io_channel_close( write );

      g_free( error );
      g_free( write );
      gtk_widget_destroy( GTK_WIDGET( pref->Prefs_Win ) );

      // Lock off!
      prefs_win_open = FALSE;
}

static void set_default_prefs( )
{
      GError *error = NULL;
      gchar *base = g_build_filename( g_get_home_dir( ), "/.config/X2/", NULL );
      gchar *fn = g_build_filename( base, "X2.conf", NULL );
      gsize bytes;
      gchar *programming_pref = "programmingfeatures:false\n";
      gchar *highlighting_pref = "syntaxhighlighting:false\n";    
      gchar *linenumbers_pref = "linenumbers:false\n";
      gchar *terminal_pref = "terminal:false\n";
      gchar *searchwords_pref = "searchinwords:false\n";
      gchar *searchcasesensitive_pref = "casesensitive:false\n";
      gchar *highlightline = "highlightline:false\n";
      const gchar *fontnamesize = "Sans 10\n";

      GIOChannel *write = g_io_channel_new_file( fn, "w", &error );

      g_io_channel_write_chars( write, programming_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, highlighting_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, linenumbers_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, terminal_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, searchwords_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, searchcasesensitive_pref, -1, &bytes, NULL );
      g_io_channel_write_chars( write, highlightline, -1, &bytes, NULL );
      g_io_channel_write_chars( write, fontnamesize, -1, &bytes, NULL );
      
      g_io_channel_close( write );
      g_free( write );
      /*g_free( error );*/
}

struct settings *load_prefs( struct settings *sets )
{
      gchar *base = g_build_filename( g_get_home_dir( ), "/.config/X2/", NULL );
      gchar *fn = g_build_filename( base, "X2.conf", NULL );

      if( !g_file_test( fn, G_FILE_TEST_EXISTS ) )
            set_default_prefs( );

      gchar *line;
      GIOChannel *read;
      read = g_io_channel_new_file( fn, "r", NULL );

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->prog_features = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->highlighting = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->lines = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->terminal = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->find_in_words = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->find_sensitive = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->highlightline = line;

      g_io_channel_read_line( read, &line, NULL, NULL, NULL );
      sets->font = line;

      g_io_channel_close( read );
      g_free( read );

      return( sets );
}

static void Enable_Programming_Check_Buttons( GtkWidget *widget, struct prefs *pref )
{
      if( !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pref->Programming_Check ) ) )
      {
            gtk_widget_set_sensitive( pref->Highlight_Check, FALSE );
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Highlight_Check ), FALSE );
            gtk_widget_set_sensitive( pref->Lines_Check, FALSE );
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Lines_Check ), FALSE );
            gtk_widget_set_sensitive( pref->Terminal_Check, FALSE );
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Terminal_Check ), FALSE );
            gtk_widget_set_sensitive( pref->HighlightLine, FALSE );
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->HighlightLine ), FALSE );
      }

      else
      {
            gtk_widget_set_sensitive( pref->Highlight_Check, TRUE );
            gtk_widget_set_sensitive( pref->Lines_Check, TRUE );
            gtk_widget_set_sensitive( pref->Terminal_Check, TRUE );
            gtk_widget_set_sensitive( pref->HighlightLine, TRUE );
      }
} 

static void Prefs( GtkWidget *widget )
{
      if( prefs_win_open )
            return;
      
      // Lock on!
      prefs_win_open = TRUE;
            
      struct prefs *pref = g_malloc( sizeof( struct prefs ) ); 

      // Create widgets
      pref->Prefs_Win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
      pref->Box = gtk_vbox_new( FALSE, 0 );
      pref->General_Box = gtk_vbox_new( FALSE, 0 );
      pref->Appearence_Box = gtk_vbox_new( FALSE, 0 );
      pref->Notes = gtk_notebook_new( );
      pref->BtnBox = gtk_hbutton_box_new( );
      pref->Apply = gtk_button_new_from_stock( GTK_STOCK_APPLY );
      pref->Cancel = gtk_button_new_from_stock( GTK_STOCK_CANCEL );
      pref->GeneralLbl = gtk_label_new( "General" );
      pref->AppearenceLbl = gtk_label_new( "Appearance" );
      pref->LicenceLbl = gtk_label_new( "Licence" );
      pref->Licence_Buffer = gtk_text_buffer_new( NULL );
      pref->Licence = gtk_text_view_new_with_buffer( GTK_TEXT_BUFFER( pref->Licence_Buffer ) );
      pref->Scroller = gtk_scrolled_window_new( NULL, NULL );
      pref->Font = gtk_font_button_new( );      
      pref->FontFrame = gtk_frame_new( "Font" );
      pref->UIBox = gtk_vbox_new( FALSE, 0 );
      pref->Programming_Box = gtk_vbox_new( FALSE, 0 );
      pref->ProgrammingFrame = gtk_frame_new( "Programming Features" );
      pref->Programming_Check = gtk_check_button_new_with_label( "Enable programming features" );
      pref->Highlight_Check = gtk_check_button_new_with_label( "Enable Syntax Highlighting" );
      pref->Lines_Check = gtk_check_button_new_with_label( "Enable Line Numbers" ); 
      pref->Terminal_Check = gtk_check_button_new_with_label( "Enable Terminal" );
      pref->FindFrame = gtk_frame_new( "Search Preferences" );
      pref->FindInWords = gtk_check_button_new_with_label( "Search inside words" );
      pref->FindSensitive = gtk_check_button_new_with_label( "Search case sensitive" );
      pref->FindBox = gtk_vbox_new( FALSE, 0 );
      pref->HighlightLine = gtk_check_button_new_with_label( "Highlight current line" );
      
      // Set widget properties
      gtk_window_set_title( GTK_WINDOW( pref->Prefs_Win ), "X2: Preferences" );
      gtk_notebook_append_page( GTK_NOTEBOOK( pref->Notes ), pref->General_Box, pref->GeneralLbl );
      gtk_notebook_append_page( GTK_NOTEBOOK( pref->Notes ), pref->Appearence_Box, pref->AppearenceLbl );
      gtk_notebook_append_page( GTK_NOTEBOOK( pref->Notes ), pref->Scroller, pref->LicenceLbl );
      gtk_button_box_set_layout( GTK_BUTTON_BOX( pref->BtnBox ), GTK_BUTTONBOX_END );
      gtk_font_button_set_title( GTK_FONT_BUTTON( pref->Font ), "Choose font" );

      // Load prefs
      if( g_strrstr( sets->prog_features, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Programming_Check ), TRUE );
      else
            Enable_Programming_Check_Buttons( NULL, pref );

      if( g_strrstr( sets->highlighting, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Highlight_Check ), TRUE );

      if( g_strrstr( sets->lines, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Lines_Check ), TRUE );

      if( g_strrstr( sets->terminal, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->Terminal_Check ), TRUE );

      if( g_strrstr( sets->find_in_words, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->FindInWords ), TRUE );

      if( g_strrstr( sets->find_sensitive, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->FindSensitive ), TRUE );

      if( g_strrstr( sets->highlightline, ":true" ) )
            gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pref->HighlightLine ), TRUE );


      gtk_font_button_set_font_name( GTK_FONT_BUTTON( pref->Font ), sets->font );

      // Add and pack widgets
      gtk_container_add( GTK_CONTAINER( pref->Prefs_Win ), GTK_WIDGET( pref->Box ) );
      gtk_container_add( GTK_CONTAINER( pref->Scroller ), GTK_WIDGET( pref->Licence ) );
      gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( pref->Scroller ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );    
      gtk_box_pack_start( GTK_BOX( pref->Box ), pref->Notes, TRUE, TRUE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->Box ), pref->BtnBox, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->BtnBox ), pref->Cancel, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->BtnBox ), pref->Apply, FALSE, FALSE, 0 );

      gtk_box_pack_start( GTK_BOX( pref->General_Box ), pref->ProgrammingFrame, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->General_Box ), pref->FindFrame, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->Appearence_Box ), pref->FontFrame, FALSE, FALSE, 0 );
      gtk_container_add( GTK_CONTAINER( pref->FontFrame ), GTK_WIDGET( pref->Font ) );
      gtk_container_add( GTK_CONTAINER( pref->ProgrammingFrame ), GTK_WIDGET( pref->Programming_Box ) );
      gtk_container_add( GTK_CONTAINER( pref->FindFrame ), GTK_WIDGET( pref->FindBox ) );
      gtk_box_pack_start( GTK_BOX( pref->Programming_Box ), pref->Programming_Check, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->Programming_Box ), pref->Highlight_Check, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->Programming_Box ), pref->Lines_Check, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->Programming_Box ), pref->Terminal_Check, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->Programming_Box ), pref->HighlightLine, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->FindBox ), pref->FindInWords, FALSE, FALSE, 0 );
      gtk_box_pack_start( GTK_BOX( pref->FindBox ), pref->FindSensitive, FALSE, FALSE, 0 );
      
      // Connect signals
      g_signal_connect( pref->Prefs_Win, "delete-event", G_CALLBACK( close_prefs ), pref );
      g_signal_connect( pref->Apply, "clicked", G_CALLBACK( save_prefs ), pref );
      g_signal_connect( pref->Cancel, "clicked", G_CALLBACK( close_prefs ), pref );
      g_signal_connect( pref->Programming_Check, "toggled", G_CALLBACK( Enable_Programming_Check_Buttons ), pref );

      // Show licence
      GtkTextIter End;
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "Copyright (c) 2011, Rock Computing\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "All rights reserved.\n\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "Redistribution and use in source and binary forms, with or without\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "modification, are permitted provided that the following conditions are met:\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "\n\t* Redistributions of source code must retain the above copyright\n\tnotice, this list of conditions and the following disclaimer.\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "\n\t* Redistributions in binary form must reproduce the above copyright\n\tnotice, this list of conditions and the following disclaimer in the\n\tdocumentation and/or other materials provided with the distribution.\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "\n\t* Neither the name Rock Computing nor the names of its contributors\n\tmay be used to endorse or promote products derived from this\n\tsoftware without specific prior written permission.\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "DISCLAIMED. IN NO EVENT SHALL ROCK COMPUTING BE LIABLE FOR ANY\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n", -1 );
      gtk_text_buffer_get_end_iter( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End );
      gtk_text_buffer_insert( GTK_TEXT_BUFFER( pref->Licence_Buffer ), &End, "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n", -1 );
      gtk_text_view_set_editable( GTK_TEXT_VIEW( pref->Licence ), FALSE );

      // Show widgets
      gtk_widget_show( pref->Prefs_Win );
      gtk_widget_show_all( pref->Box );
}

static void S1( GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, struct search_data *sd ) { Search( sd ); }
static void S2( GtkEntry *entry, struct search_data *sd ) { Search( sd ); }

static void Search( struct search_data *sd )
{
      struct node *doc = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( sd->Notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( sd->Notebook ) ) ) ), "document" );
      const gchar *search = gtk_entry_get_text( GTK_ENTRY( sd->Search ) );

      GtkTextIter mstart, mend, iter, start, end;
      GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW( doc->Doc ) );

      GtkSourceSearchFlags search_flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY;

      if( !g_strrstr( sets->find_sensitive, ":true" ) )
            search_flags = search_flags | GTK_SOURCE_SEARCH_CASE_INSENSITIVE;
      
      GtkTextMark *last_pos = gtk_text_buffer_get_mark( buffer, sd->textmark );
      gtk_text_buffer_get_bounds( buffer, &start, &end );
      
      if( !last_pos )
      {
            gtk_text_buffer_create_mark( buffer, sd->textmark, &start, FALSE );
            last_pos = gtk_text_buffer_get_mark( buffer, sd->textmark );
      }

      gtk_text_buffer_get_iter_at_mark( buffer, &iter, last_pos );

      if( !g_strrstr( sets->find_in_words, ":true" ) )
      {
            gchar *stmp = g_strconcat( " ", search, " ", NULL );
            search = stmp;
      }

      if( gtk_source_iter_forward_search( &iter, search, search_flags, &mstart, &mend, NULL ) )
      {
            gtk_text_buffer_create_mark( buffer, sd->textmark, &mend, FALSE );
            gtk_text_view_scroll_mark_onscreen( GTK_TEXT_VIEW( doc->Doc ), last_pos );
            gtk_text_buffer_select_range( buffer, &mstart, &mend );
      }

      else
            gtk_text_buffer_delete_mark( GTK_TEXT_BUFFER( buffer ), last_pos ); 
}

static void C1( GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, struct search_data *sd ) { Change( sd ); }
static void C2( GtkEntry *entry, struct search_data *sd ) { Change( sd ); }

static void Change( struct search_data *tmp )
{
      struct node *doc = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( tmp->Notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( tmp->Notebook ) ) ) ), "document" );
      const gchar *replace_text = gtk_entry_get_text( GTK_ENTRY( doc->Replace2 ) );
      GtkTextIter start, end, iter;
      GtkTextMark *last_pos = gtk_text_buffer_get_mark( GTK_TEXT_BUFFER( doc->Buffer ), tmp->textmark );
      
      if( last_pos )
      {
            gtk_text_buffer_get_selection_bounds( GTK_TEXT_BUFFER( doc->Buffer ), &start, &end );
            gtk_text_buffer_create_mark( GTK_TEXT_BUFFER( doc->Buffer ), "paste", &start, FALSE );
            gtk_text_buffer_delete( GTK_TEXT_BUFFER( doc->Buffer ), &start, &end );
            gtk_text_buffer_get_iter_at_mark( GTK_TEXT_BUFFER( doc->Buffer ), &iter, last_pos );
            gtk_text_buffer_insert( GTK_TEXT_BUFFER( doc->Buffer ), &iter, replace_text, -1 );
      }
}

static void G1( GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, struct node *tmp ) { go_to_line( tmp ); }
static void G2( GtkEntry *entry, struct node *tmp ) { go_to_line( tmp ); }

static void go_to_line( struct node *tmp )
{
      gint line = atoi( gtk_entry_get_text( GTK_ENTRY( tmp->JumpSpin ) ) );
            
      if( line )
      {
            GtkTextIter iter;
            gtk_text_buffer_get_iter_at_line( GTK_TEXT_BUFFER( tmp->Buffer ), &iter, line -1 );
            gtk_text_view_scroll_to_iter( GTK_TEXT_VIEW( tmp->Doc ), &iter, 0.0, TRUE, 0, 0 );
            gtk_text_buffer_place_cursor( GTK_TEXT_BUFFER( tmp->Buffer ), &iter );
      }
}

static void Close( GtkWidget *widget, struct str_data *tmp )
{     
      gint page_num = gtk_notebook_page_num( GTK_NOTEBOOK( tmp->Notebook ), tmp->Widget );
      struct node *doc = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( tmp->Notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( tmp->Notebook ) ) ) ), "document" );
      
      if( gtk_text_buffer_get_modified( GTK_TEXT_BUFFER( doc->Buffer ) ) )
      {
            gtk_notebook_set_current_page( GTK_NOTEBOOK( tmp->Notebook ), page_num );
            GtkWidget *warning = gtk_dialog_new_with_buttons(
            "Save file?",
                 NULL,
                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                 GTK_STOCK_YES,
                 GTK_RESPONSE_YES,
                 GTK_STOCK_NO,
                 GTK_RESPONSE_NO,
                 NULL );

            gint result = gtk_dialog_run( GTK_DIALOG( warning ) );
                  
            if( result == GTK_RESPONSE_YES )
                  Save( NULL, tmp->Notebook );

            gtk_widget_destroy( warning );
      }
      
      gtk_notebook_remove_page( GTK_NOTEBOOK( tmp->Notebook ), page_num );

      if( gtk_notebook_get_n_pages( GTK_NOTEBOOK( tmp->Notebook ) ) == 0 )
            gtk_main_quit( );

      g_free( tmp );
}

static void BufferChanged( GtkWidget *widget, struct node *tmp )
{
      if( !gtk_text_buffer_get_modified( GTK_TEXT_BUFFER( tmp->Buffer ) ) )
      {
            const gchar *text = gtk_label_get_text( GTK_LABEL( tmp->Label ) );
            const gchar *new_text = g_strconcat( text, "* ", NULL );
            gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( tmp->Buffer ), TRUE );
            gtk_label_set_text( GTK_LABEL( tmp->Label ), new_text );
      }

      // Create the spin button adjustment, then get the number of lines followed be re-setting the upper limit
      GtkAdjustment *adjust = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( tmp->JumpSpin ) );
      gint lines = gtk_text_buffer_get_line_count( GTK_TEXT_BUFFER( tmp->Buffer ) );
      gtk_adjustment_set_upper( adjust, lines );
}

static gboolean destroy( GtkWidget *widget, GdkEvent *event, GtkWidget *notebook ) 
{ 
      gint pages = gtk_notebook_get_n_pages( GTK_NOTEBOOK( notebook ) ) -1;
      gtk_main_quit( );
      gint i;

      for( i = 0; i <= pages; i++ )
      {
            struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

            if( gtk_text_buffer_get_modified( GTK_TEXT_BUFFER( tmp->Buffer ) ) )
            {
                  gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), i );
                  GtkWidget *warning = gtk_dialog_new_with_buttons(
                  "Save file?",
                        NULL,
                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                        GTK_STOCK_YES,
                        GTK_RESPONSE_YES,
                        GTK_STOCK_NO,
                        GTK_RESPONSE_NO,
                        NULL );

                  gint result = gtk_dialog_run( GTK_DIALOG( warning ) );
                  
                  if( result == GTK_RESPONSE_YES )
                        Save( NULL, notebook );

                  gtk_widget_destroy( warning );
            }
      }

      return( TRUE );
}

static void drag_data_received_handler( GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint time, GtkWidget *notebook )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      if( gtk_text_buffer_get_char_count( GTK_TEXT_BUFFER( tmp->Buffer ) ) )
      {
            New( NULL, notebook ); 
            tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );
      }

      gchar *file = selection_data->data;
      g_strchomp( file );
      gchar **s = g_strsplit( file, "file://", 2 );
      gchar *t = s[ 1 ];
      gchar **u = g_strsplit( t, "%20", 0 );
      gchar *fn = "";

      if( g_strrstr( s[ 1 ], "%20" ) )
      {
            gint i = 0;
            for( ; ; )
            {
                  if( u[ i ] )
                        fn = g_strconcat( fn, " ", u[ i ], NULL );
                  else
                        break;
                  i++;
            }

            g_strstrip( fn );
            tmp->Name = fn;         
      }

      else
            tmp->Name = s[ 1 ];
      
      gchar *contents;

      g_file_get_contents( tmp->Name, &contents, NULL, NULL );
      gtk_text_buffer_set_text( GTK_TEXT_BUFFER( tmp->Buffer ), contents, -1 );
      gtk_label_set_text( GTK_LABEL( tmp->Label ), g_strconcat( g_path_get_basename( tmp->Name ), " ", NULL ) );
      gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( tmp->Buffer ), FALSE );

      if( tmp )   
            gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", tmp->Name, NULL ) );

      // Syntax highlighting
      highlight_code( tmp );
      g_free( contents );
}

static void write_file( struct node *tmp )
{
      GtkTextIter StartIter, EndIter;
      gtk_text_buffer_get_bounds( GTK_TEXT_BUFFER( tmp->Buffer ), &StartIter, &EndIter );
      g_file_set_contents( tmp->Name, gtk_text_buffer_get_text( GTK_TEXT_BUFFER( tmp->Buffer ), &StartIter, &EndIter, TRUE ), -1, NULL );
}

static void Set_Title( GtkWidget *notebook, gpointer page, guint page_num, gpointer user_data )
{
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      if( tmp )   
            gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", tmp->Name, NULL ) );
}

static GtkWidget *open_with( gchar *fn, GtkWidget *notebook )
{
      New( NULL, notebook );
      struct node *tmp = g_object_get_data( G_OBJECT( gtk_notebook_get_nth_page( GTK_NOTEBOOK( notebook ), gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) ) ), "document" );

      tmp->Name = fn;   
      gchar *contents;

      g_file_get_contents( tmp->Name, &contents, NULL, NULL );
      gtk_text_buffer_set_text( GTK_TEXT_BUFFER( tmp->Buffer ), contents, -1 );
      gtk_label_set_text( GTK_LABEL( tmp->Label ), g_strconcat( g_path_get_basename( tmp->Name ), " ", NULL ) );
      gtk_text_buffer_set_modified( GTK_TEXT_BUFFER( tmp->Buffer ), FALSE );

      gtk_window_set_title( GTK_WINDOW( window ), g_strconcat( "X2: ", tmp->Name, NULL ) );
      // Syntax highlighting
      highlight_code( tmp );
      g_free( contents );

      return( tmp->Doc );
}

static void highlight_code( struct node *tmp )
{
      if( g_strrstr( sets->highlighting, ":true" ) )
      {
            GtkSourceLanguage *lang;
            GtkSourceLanguageManager *lm = gtk_source_language_manager_new( );
            lang = gtk_source_language_manager_guess_language( lm, tmp->Name, NULL );
            gtk_source_buffer_set_language( tmp->Buffer, lang );
      }
}

Generated by  Doxygen 1.6.0   Back to index