1#!/usr/local/bin/perl -w 2################################################################################ 3# xrdesktop2, a gtk-perl frontend for rdesktop # 4# Copyright (C) 2002 David Kovach (xrdesktop 0.x-1.x) # 5# Copyright (C) 2014-2015 Peter TKATCHENKO, Chris Hutchinson # 6# Ported to Gtk2 by Peter TKATCHENKO, 2014 # 7# Maintained by Chris Hutchinson, 2015 # 8# # 9# Redistribution and use in source and binary forms, with or without # 10# modification, are permitted provided that the following conditions are met: # 11# # 12# 1) Redistributions of source code must retain the above copyright notice, # 13# this list of conditions and the following disclaimer. # 14# # 15# 2) Redistributions in binary form must reproduce the above copyright notice, # 16# this list of conditions and the following disclaimer in the documentation # 17# and/or other materials provided with the distribution. # 18# # 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # 20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # 21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # 22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # 23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # 24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # 25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # 26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # 27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # 28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 29# POSSIBILITY OF SUCH DAMAGE. # 30################################################################################ 31 32use Gtk2 -init; 33use Gtk2::SimpleList; 34use strict; 35use vars qw($ourname $VERSION); 36$ourname = qq(Xrdesktop2); 37#$VERSION = v2.00; 38$VERSION = qq(2.00); 39 40my $false = 0; 41my $true = 1; 42 43my $window; 44my $box1; 45my $scrolled_window1; 46my $buttonbox1; 47my $button1; 48my $button2; 49my $button3; 50my $button4; 51my $button5; 52my $list1; 53my %ip_hash; 54my %uname_hash; 55my %geom_hash; 56my %fullscreen_hash; 57my %bitmap_upd_hash; 58my %kmap_hash; 59my %license_hash; 60my %passthru_hash; 61my $machine_name; 62my $machine_ip; 63my $machine_uname; 64my $machine_geom; 65my $machine_fs; 66my $machine_bitmap_upd; 67my $machine_kmap; 68my $machine_lic; 69my $machine_passthru; 70my $raw_data; 71my $field_type; 72my $field_data; 73my $machina; 74my @machines; 75my @temp; 76my $selected_machine; 77my $selected_machine_ip; 78my $selected_uname; 79my $selected_geom; 80my $selected_fs; 81my $selected_bitmap_upd; 82my $selected_kmap; 83my $selected_kmap_hex; 84my $selected_lic; 85my $selected_passthru; 86my $dialog1; 87my $dialog_button_ok; 88my $dialog_button_cancel; 89my $name_entry; 90my $ip_entry; 91my $uname_entry; 92my $dialog2; 93my $combo1; 94my $combo2; 95my $fs_checkbox; 96my $bmp_checkbox; 97my $lic_checkbox; 98my $passthru_entry; 99my $passthru; 100my $indexmax=0; 101 102# the BIGASS list of keymaps. fear its awesome girth and stuff. 103## 02/10/2003 updated the list to work with rdesktop 1.2 and the 104## new way they do keyboard layouts...feh 105## left all the hex codes for which i could not find mappings as comments 106## in the hopes that someday it will get fixed. 107## also note that some of these are approximations and may or may 108## not work at all. 109my %kmap_trans_hash = ( 110 "Albanian" => "en-us", 111# "Arabic 101" => "0x00000401", 112# "Arabic 102 AZERTY" => "0x00020401", 113# "Arabic 102" => "0x00010401", 114# "Armenian Eastern" => "0x0000042b", 115# "Armenian Western" => "0x0001042b", 116# "Azeri Cyrillic" => "0x0000082c", 117# "Azeri Latin" => "0x0000042c", 118# "Belarusian" => "0x00000423", 119# "Belgian Comma" => "0x0001080c", 120 "Belgian Dutch" => "be", 121 "Belgian French" => "be", 122 "Bulgarian Latin" => "bg", 123# "Bulgarian" => "0x00000402", 124 "Canadian French legacy" => "cf", 125 "Canadian French" => "en-us", 126# "Canadian Multilingual Standard" => "0x00011009", 127# "Chinese MS-PinYin98" => "0xe00e0804", 128# "Chinese NeiMa" => "0xe0050804", 129# "Chinese QuanPin" => "0xe0010804", 130# "Chinese ShuangPin" => "0xe0020804", 131 "Chinese US Keyboard" => "ch", 132# "Chinese ZhengMa" => "0xe0030804", 133# "Chinese Alphanumeric" => "0xe01f0404", 134# "Chinese Array" => "0xe0050404", 135# "Chinese Big5 Code" => "0xe0040404", 136# "Chinese ChangJie" => "0xe0020404", 137# "Chinese DaYi" => "0xe0060404", 138# "Chinese New ChangJie" => "0xe0090404", 139# "Chinese New Phoneetic" => "0xe0080404", 140# "Chinese Phonetic" => "0xe0010404", 141# "Chinese Quick" => "0xe0030404", 142 "Chinese US Keyboard" => "ch", 143# "Chinese Unicode" => "0xe0070404", 144# "Croatian" => "0x0000041a", 145# "Croatian Specific" => "0x0000041a", 146 "Czech QWERTY" => "cz", 147# "Czech ProgrammerS" => "0x00020405", 148 "Czech" => "cz", 149 "Danish" => "dk", 150# "Devanagari INSCRIPT" => "0x00000439", 151 "Dutch" => "nl", 152 "Estonian" => "et", 153# "Faeroese" => "0x00000438", 154# "Farsi" => "0x00000429", 155 "Finnish" => "su", 156 "French" => "fr", 157# "Gaelic" => "0x00011809", 158# "Georgian" => "0x00000437", 159# changed the German keymap string from "gr" to "de" 160# at the behest of Tobias Mohrluder. Thanks! 161# hopefully this is right :) 162 "German IBM" => "de", 163 "German" => "de", 164# "Greek 220 Latin" => "0x00030408", 165 "Greek 220" => "gk", 166# "Greek 319 Latin" => "0x00040408", 167 "Greek 319" => "gk", 168 "Greek Latin" => "gk", 169# "Greek Polytonic" => "0x00060408", 170 "Greek" => "gk", 171# "Hebrew" => "0x0000040d", 172# "Hindi Traditional" => "0x00010439", 173 "Hungarian 101-key" => "hu", 174 "Hungarian" => "hu", 175 "Icelandic" => "is", 176 "Irish" => "en-us", 177 "Italian 142" => "it", 178 "Italian" => "it", 179# "Japanese Input System" => "0xe0010411", 180 "Japanese" => "jp", 181# "Japanese 106" => "0x00000411", 182# "Japanese pc98x1" => "0x00000411", 183# "Kazakh" => "0x0000043f", 184# "Korean Hangul MS-IME98" => "0xe0010412", 185 "Korean Hangul" => "ko", 186 "Latin American" => "la", 187 "Latvian QWERTY" => "en-us", 188# "Latvian" => "0x00000426", 189# "Lithuanian IBM" => "0x00000427", 190# "Lithuanian" => "0x00010427", 191# "Macedonian FYROM" => "0x0000042f", 192# "Marathi" => "0x0000044e", 193 "Norwegian" => "no", 194 "Polish 214" => "pl", 195 "Polish Programmers" => "pl", 196 "Portuguese Brazilian ABNT" => "br", 197# "Portuguese Brazilian ABNT2" => "0x00010416", 198 "Portuguese" => "po", 199 "Romanian" => "ro", 200 "Russian Typewriter" => "ru", 201 "Russian" => "ru", 202# "Russian KO18-R" => "0x00000419", 203 "Serbian Cyrillic" => "en-us", 204# "Serbian Latin" => "0x0000081a", 205 "Slovak QWERTY" => "sl", 206 "Slovak" => "sl", 207# "Slovak Programmers" => "0x0000041b", 208 "Slovenian" => "yu", 209#altered spanish keyboard courtesy of Jonay Gomez 210 "Spanish Variation" => "es", 211# "Spanish" => "0x0000040a", 212 "Swedish" => "sv", 213 "Swiss French" => "sf", 214# "Swiss German" => "0x0000080", 215# "Tamil" => "0x00000449", 216# "Tatar" => "0x00000444", 217# "Thai Kedmanee non-shiftlock" => "0x0002041e", 218# "Thai Kedmanee" => "0x0000041e", 219# "Thai Pattachote non-shiftlock" => "0x0003041e", 220# "Thai Pattachote" => "0x0001041e", 221 "Turkish F" => "tr", 222 "Turkish Q" => "tr", 223# "US English Talbe for IBM Arabic 238_L" => "0x00050409", 224 "US" => "en-us", 225# "US phantom key ver" => "0x00000409", 226# "Ukranian" => "0x00000422", 227 "English" => "en-gb", 228 "US Dvorak left" => "usl", 229 "US Dvorak right" => "usr", 230 "US Dvorak" => "dv", 231 "US International" => "en-us", 232# "Uzbek Cyrillic" => "0x00000843", 233# "Vietnamese" => "0x0000042a", 234 "yu" => "yu", 235 "cf" => "cf", 236 "us9" => "en-us", 237); 238 239# create the window 240$window = Gtk2::Window->new; 241$window->signal_connect( "delete_event", sub { Gtk2->main_quit } ); 242$window->set_default_size( 940, 600 ); 243$window->set_border_width( 2 ); 244$window->set_title("$ourname :: v$VERSION"); 245 246# make our first box 247$box1 = Gtk2::VBox->new; 248$box1->set_spacing(8); 249 250# create the list, assign a signal to handle change of selection 251$list1 = Gtk2::SimpleList->new ("Name", "text", "Hostname/IP", "text", "Username", "text", "Keymap", "text", "Geometry", "text", "Fullscreen", "text", "Force Bitmap Updates", "text", "Do Not Request License", "text", "CMD Vars", "text" ); 252 253# this is the scrolled window to put the List widget inside 254$scrolled_window1 = Gtk2::ScrolledWindow->new; 255$scrolled_window1->set_policy( "automatic", "automatic" ); 256$scrolled_window1->add_with_viewport( $list1 ); 257$box1->pack_start( $scrolled_window1, $true, $true, 0 ); 258$window->add( $box1 ); 259 260$list1->signal_connect( 'cursor-changed', \&list_sel_row ); 261$list1->signal_connect( 'row_activated', \&rdesque_connect ); 262 263# see the sub at the end of the script for info 264populate_clist_from_config(); 265 266# Make some buttons 267$buttonbox1 = new Gtk2::HButtonBox(); 268$button1 = new Gtk2::Button( "Connect" ); 269$button2 = new Gtk2::Button( "Add" ); 270$button3 = new Gtk2::Button( "Delete" ); 271$button4 = new Gtk2::Button( "Edit" ); 272$button5 = new Gtk2::Button( "Quit" ); 273 274# tell them what to do 275$button1->signal_connect( "clicked", \&rdesque_connect ); 276$button2->signal_connect( "clicked", \&rdesque_add ); 277$button3->signal_connect( "clicked", \&rdesque_delete ); 278$button4->signal_connect( "clicked", \&rdesque_edit ); 279$button5->signal_connect( "clicked", sub { Gtk2->main_quit } ); 280 281# put stuff in the window 282$box1->pack_start( $buttonbox1, $false, $false, 0 ); 283$buttonbox1->add( $button1 ); 284$buttonbox1->add( $button2 ); 285$buttonbox1->add( $button3 ); 286$buttonbox1->add( $button4 ); 287$buttonbox1->add( $button5 ); 288 289$window->show_all(); 290 291main Gtk2; 292 293exit( 0 ); 294 295# Subroutines 296 297# simple sub, to launch rdesktop with the configured info 298# when the connect button is clicked. rather tidy :) 299# remove the print line before the system call if you like quietness 300sub rdesque_connect 301{ 302 my $buffer; 303# FIXME need to create man/pod page for these and add -q (quiet) switch 304 if( $selected_uname ) { $buffer = $buffer . " -u $selected_uname"; } 305 if( $selected_geom ) { $buffer = $buffer . " -g $selected_geom"; } 306 if( $selected_kmap_hex ) { $buffer = $buffer . " -k $selected_kmap_hex"; } 307 if( $selected_fs eq "true" ) { $buffer = $buffer . " -f"; } 308 if( $selected_bitmap_upd eq "true" ) { $buffer = $buffer . " -b"; } 309 if( $selected_lic eq "true" ) { $buffer = $buffer . " -l"; } 310 if( $selected_passthru ) { $buffer = $buffer . " $selected_passthru"; } 311 312#make the title whatever the string of the selected machine name is 313#instead of the machine's ip, courtesy of Jonay Gomez. thanks! 314#moved up here at the behest of Tobias Mohrluder. Thanks! 315 if( $selected_machine ) { $buffer = $buffer . " -T \"$selected_machine\""; } 316 317 if( $selected_machine_ip ) { $buffer = $buffer . " $selected_machine_ip"; } 318 else { die "No IP/Hostname selected! Aborting.\n"; } 319 320 print "commandline is \"rdesktop $buffer\"\n"; 321 system("rdesktop $buffer \&"); 322} 323 324# sub to add an entry into the list of machines to choose from 325# all this sub actually does is set up the dialog box to 326# collect the info, the do_add_server() sub is what 327# really does all the updating of info 328# yes i know the layout stuff is effin nasty 329# deal with it, i'm new at this gooey stuff... :P 330sub rdesque_add 331{ 332 $dialog1 = new Gtk2::Dialog(); 333 $dialog1->set_title("Add Server"); 334 $dialog_button_ok = new Gtk2::Button( "Ok" ); 335 $dialog_button_cancel = new Gtk2::Button( "Cancel" ); 336 $dialog_button_ok->signal_connect( "clicked", \&do_add_server ); 337 $dialog_button_cancel->signal_connect( "clicked", sub { $dialog1->destroy(); } ); 338 339 $name_entry = new Gtk2::Entry( ); 340 $ip_entry = new Gtk2::Entry( ); 341 $uname_entry = new Gtk2::Entry( ); 342 $passthru_entry = new Gtk2::Entry( ); 343 344 my $label1 = new Gtk2::Label( "Enter a name for this server: " ); 345 my $label2 = new Gtk2::Label( "Enter an IP address or hostname to connect to: " ); 346 my $label3 = new Gtk2::Label( "Resolution: " ); 347 my $label4 = new Gtk2::Label( "Username: " ); 348 my $label5 = new Gtk2::Label( "Keyboard Mapping: " ); 349 my $label6 = new Gtk2::Label( "Additional Variables to pass: " ); 350 351 $label1->set_justify( "left" ); 352 $label2->set_justify( "left" ); 353 $label3->set_justify( "left" ); 354 $label4->set_justify( "left" ); 355 $label5->set_justify( "left" ); 356 $label6->set_justify( "left" ); 357 358 my $vbox1 = new Gtk2::VBox( $false, 0 ); 359 my $vbox2 = new Gtk2::VBox( $false, 0 ); 360 my $vbox3 = new Gtk2::VBox( $false, 0 ); 361 my $vbox4 = new Gtk2::VBox( $false, 0 ); 362 my $vbox5 = new Gtk2::VBox( $false, 0 ); 363 my $vbox6 = new Gtk2::VBox( $false, 0 ); 364 my $vbox7 = new Gtk2::VBox( $false, 0 ); 365 366 my $hbox1 = new Gtk2::HBox( $false, 0 ); 367 my $hbox2 = new Gtk2::HBox( $false, 0 ); 368 my $hbox3 = new Gtk2::HBox( $false, 0 ); 369 my $hbox4 = new Gtk2::HBox( $false, 0 ); 370 my $hbox5 = new Gtk2::HBox( $false, 0 ); 371 my $hbox6 = new Gtk2::HBox( $false, 0 ); 372 my $hbox7 = new Gtk2::HBox( $false, 0 ); 373 374 $combo1 = new Gtk2::Combo(); 375 $combo2 = new Gtk2::Combo(); 376 my @combo_list = ("640x480", "800x600", "1024x768", "1280x1024", "1400x1050", "1600x1200"); 377 my @combo_list2 = sort keys %kmap_trans_hash; 378 $combo1->set_popdown_strings( @combo_list ); 379 $combo1->set_use_arrows_always( $true ); 380 $combo1->set_value_in_list( $false, $true ); 381 $combo2->set_popdown_strings( @combo_list2 ); 382 $combo2->set_use_arrows_always( $true ); 383 $combo2->set_value_in_list( $true, $false ); 384 # $combo2->entry->set_text( "US" ); 385 $fs_checkbox = new Gtk2::CheckButton( "Fullscreen On" ); 386 $bmp_checkbox = new Gtk2::CheckButton( "Force Bitmap Update" ); 387 $lic_checkbox = new Gtk2::CheckButton( "Do Not Request License" ); 388 389 $dialog1->vbox->set_homogeneous( $false ); 390 391 $dialog1->vbox->pack_start( $hbox1, $false, $false, 0 ); 392 $hbox1->pack_start( $vbox1, $false, $false, 0 ); 393 $vbox1->pack_start( $label1, $false, $false, 0 ); 394 $vbox1->pack_start( $name_entry, $false, $false, 0 ); 395 396 $dialog1->vbox->pack_start( $hbox2, $false, $false, 0 ); 397 $hbox2->pack_start( $vbox2, $false, $false, 0 ); 398 $vbox2->pack_start( $label2, $false, $false, 0 ); 399 $vbox2->pack_start( $ip_entry, $false, $false, 0 ); 400 401 $dialog1->vbox->pack_start( $hbox4, $false, $false, 0 ); 402 $hbox4->pack_start( $vbox4, $false, $false, 0 ); 403 $vbox4->pack_start( $label4, $false, $false, 0 ); 404 $vbox4->pack_start( $uname_entry, $false, $false, 0 ); 405 406 $dialog1->vbox->pack_start( $hbox7, $false, $false, 0 ); 407 $hbox7->pack_start( $vbox7, $false, $false, 0 ); 408 $vbox7->pack_start( $label6, $false, $false, 0 ); 409 $vbox7->pack_start( $passthru_entry, $false, $false, 0 ); 410 411 $dialog1->vbox->pack_start( $hbox3, $false, $false, 0 ); 412 $hbox3->pack_start( $vbox3, $false, $false, 0 ); 413 $vbox3->pack_start( $label3, $false, $false, 0 ); 414 $vbox3->pack_start( $combo1, $false, $false, 0 ); 415 416 $dialog1->vbox->pack_start( $hbox5, $false, $false, 0 ); 417 $hbox5->pack_start( $vbox5, $false, $false, 0 ); 418 $vbox5->pack_start( $label5, $false, $false, 0 ); 419 $vbox5->pack_start( $combo2, $false, $false, 0 ); 420 421 $dialog1->vbox->pack_start( $hbox6, $false, $false, 0 ); 422 $hbox6->pack_start( $vbox6, $false, $false, 0 ); 423 $vbox6->pack_start( $fs_checkbox, $false, $false, 0 ); 424 $vbox6->pack_start( $bmp_checkbox, $false, $false, 0 ); 425 $vbox6->pack_start( $lic_checkbox, $false, $false, 0 ); 426 427 $dialog1->action_area->pack_start( $dialog_button_ok, $true, $true, 0 ); 428 $dialog1->action_area->pack_start( $dialog_button_cancel, $true, $true, 0 ); 429 430 $name_entry->set_text( $selected_machine ); 431 $ip_entry->set_text( $ip_hash{$selected_machine} ); 432 $uname_entry->set_text( $uname_hash{$selected_machine} ); 433 $passthru_entry->set_text( $passthru_hash{$selected_machine} ); 434 $combo1->entry->set_text( $geom_hash{$selected_machine} ); 435 $combo2->entry->set_text( $kmap_hash{$selected_machine} ); 436 if( $fullscreen_hash{$selected_machine} eq "true") 437 { 438 $fs_checkbox->set_active( $true ); 439 } 440 else { $fs_checkbox->set_active( $false ); } 441 if( $bitmap_upd_hash{$selected_machine} eq "true" ) 442 { 443 $bmp_checkbox->set_active( $true ); 444 } 445 else { $bmp_checkbox->set_active( $false ); } 446 if( $license_hash{$selected_machine} eq "true" ) 447 { 448 $lic_checkbox->set_active( $true ); 449 } 450 else { $lic_checkbox->set_active( $false ); } 451 452 $dialog1->show_all(); 453} 454 455# remove a machine entry from the list 456sub rdesque_delete 457{ 458 my $name_deleted; 459 my $ip_deleted; 460 $name_deleted = $selected_machine; 461 $ip_deleted = $ip_hash{$selected_machine}; 462 delete $ip_hash{$selected_machine}; 463 delete $uname_hash{$selected_machine}; 464 delete $geom_hash{$selected_machine}; 465 delete $fullscreen_hash{$selected_machine}; 466 delete $bitmap_upd_hash{$selected_machine}; 467 delete $kmap_hash{$selected_machine}; 468 delete $license_hash{$selected_machine}; 469 delete $passthru_hash{$selected_machine}; 470 write_out_config(); 471 print "Server deleted: name = $name_deleted, ip/hostname = $ip_deleted\n"; 472 populate_clist_from_config(); 473} 474 475# change an existing entry in the list 476# much like the rdesque_add() sub, all this does 477# set up a dialog to display the info and change it 478# all the real legwork is done by do_edit_server() 479# yes, the layout stuff is nasty, see comments for rdesque_add() 480sub rdesque_edit 481{ 482 $dialog2 = new Gtk2::Dialog(); 483 $dialog_button_ok = new Gtk2::Button( "Ok" ); 484 $dialog_button_cancel = new Gtk2::Button( "Cancel" ); 485 $dialog_button_ok->signal_connect( "clicked", \&do_edit_server ); 486 $dialog_button_cancel->signal_connect( "clicked", sub { $dialog2->destroy(); } ); 487 488 $name_entry = new Gtk2::Entry( ); 489 $ip_entry = new Gtk2::Entry( ); 490 $uname_entry = new Gtk2::Entry( ); 491 $passthru_entry = new Gtk2::Entry( ); 492 493 my $label1 = new Gtk2::Label( "Enter a name for this server: " ); 494 my $label2 = new Gtk2::Label( "Enter an IP address or hostname to connect to: "); 495 my $label3 = new Gtk2::Label( "Resolution: " ); 496 my $label4 = new Gtk2::Label( "Username: " ); 497 my $label5 = new Gtk2::Label( "Keyboard Mapping: " ); 498 my $label6 = new Gtk2::Label( "Additional Variables to pass: " ); 499 500 $label1->set_justify( "left" ); 501 $label2->set_justify( "left" ); 502 $label3->set_justify( "left" ); 503 $label4->set_justify( "left" ); 504 $label5->set_justify( "left" ); 505 $label6->set_justify( "left" ); 506 507 my $vbox1 = new Gtk2::VBox( $false, 0 ); 508 my $vbox2 = new Gtk2::VBox( $false, 0 ); 509 my $vbox3 = new Gtk2::VBox( $false, 0 ); 510 my $vbox4 = new Gtk2::VBox( $false, 0 ); 511 my $vbox5 = new Gtk2::VBox( $false, 0 ); 512 my $vbox6 = new Gtk2::VBox( $false, 0 ); 513 my $vbox7 = new Gtk2::VBox( $false, 0 ); 514 515 my $hbox1 = new Gtk2::HBox( $false, 0 ); 516 my $hbox2 = new Gtk2::HBox( $false, 0 ); 517 my $hbox3 = new Gtk2::HBox( $false, 0 ); 518 my $hbox4 = new Gtk2::HBox( $false, 0 ); 519 my $hbox5 = new Gtk2::HBox( $false, 0 ); 520 my $hbox6 = new Gtk2::HBox( $false, 0 ); 521 my $hbox7 = new Gtk2::HBox( $false, 0 ); 522 523 $combo1 = new Gtk2::Combo(); 524 $combo2 = new Gtk2::Combo(); 525 my @combo_list = ("640x480", "800x600", "1024x768", "1280x1024", "1400x1050", "1600x1200"); 526 my @combo_list2 = sort keys %kmap_trans_hash; 527 $combo1->set_popdown_strings( @combo_list ); 528 $combo1->set_use_arrows_always( $true ); 529 $combo1->set_value_in_list( $false, $true ); 530 $combo2->set_popdown_strings( @combo_list2 ); 531 $combo2->set_use_arrows_always( $true ); 532 $combo2->set_value_in_list( $true, $false ); 533 534 $fs_checkbox = new Gtk2::CheckButton( "Fullscreen On" ); 535 $bmp_checkbox = new Gtk2::CheckButton( "Force Bitmap Update" ); 536 $lic_checkbox = new Gtk2::CheckButton( "Do Not Request License" ); 537 538 $dialog2->vbox->set_homogeneous( $false ); 539 540 $dialog2->vbox->pack_start( $hbox1, $false, $false, 0 ); 541 $hbox1->pack_start( $vbox1, $false, $false, 0 ); 542 $vbox1->pack_start( $label1, $false, $false, 0 ); 543 $vbox1->pack_start( $name_entry, $false, $false, 0 ); 544 545 $dialog2->vbox->pack_start( $hbox2, $false, $false, 0 ); 546 $hbox2->pack_start( $vbox2, $false, $false, 0 ); 547 $vbox2->pack_start( $label2, $false, $false, 0 ); 548 $vbox2->pack_start( $ip_entry, $false, $false, 0 ); 549 550 $dialog2->vbox->pack_start( $hbox4, $false, $false, 0 ); 551 $hbox4->pack_start( $vbox4, $false, $false, 0 ); 552 $vbox4->pack_start( $label4, $false, $false, 0 ); 553 $vbox4->pack_start( $uname_entry, $false, $false, 0 ); 554 555 $dialog2->vbox->pack_start( $hbox7, $false, $false, 0 ); 556 $hbox4->pack_start( $vbox7, $false, $false, 0 ); 557 $vbox4->pack_start( $label6, $false, $false, 0 ); 558 $vbox4->pack_start( $passthru_entry, $false, $false, 0 ); 559 560 $dialog2->vbox->pack_start( $hbox3, $false, $false, 0 ); 561 $hbox3->pack_start( $vbox3, $false, $false, 0 ); 562 $vbox3->pack_start( $label3, $false, $false, 0 ); 563 $vbox3->pack_start( $combo1, $false, $false, 0 ); 564 565 $dialog2->vbox->pack_start( $hbox6, $false, $false, 0 ); 566 $hbox6->pack_start( $vbox6, $false, $false, 0 ); 567 $vbox6->pack_start( $label5, $false, $false, 0 ); 568 $vbox6->pack_start( $combo2, $false, $false, 0 ); 569 570 $dialog2->vbox->pack_start( $hbox5, $false, $false, 0 ); 571 $hbox5->pack_start( $vbox5, $false, $false, 0 ); 572 $vbox5->pack_start( $fs_checkbox, $false, $false, 0 ); 573 $vbox5->pack_start( $bmp_checkbox, $false, $false, 0 ); 574 $vbox5->pack_start( $lic_checkbox, $false, $false, 0 ); 575 576 $dialog2->action_area->pack_start( $dialog_button_ok, $true, $true, 0 ); 577 $dialog2->action_area->pack_start( $dialog_button_cancel, $true, $true, 0 ); 578 579 $name_entry->set_text( $selected_machine ); 580 $ip_entry->set_text( $ip_hash{$selected_machine} ); 581 $uname_entry->set_text( $uname_hash{$selected_machine} ); 582 $passthru_entry->set_text( $passthru_hash{$selected_machine} ); 583 $combo1->entry->set_text( $geom_hash{$selected_machine} ); 584 $combo2->entry->set_text( $kmap_hash{$selected_machine} ); 585 if( $fullscreen_hash{$selected_machine} eq "true") 586 { 587 $fs_checkbox->set_active( $true ); 588 } 589 else { $fs_checkbox->set_active( $false ); } 590 if( $bitmap_upd_hash{$selected_machine} eq "true" ) 591 { 592 $bmp_checkbox->set_active( $true ); 593 } 594 else { $bmp_checkbox->set_active( $false ); } 595 if( $license_hash{$selected_machine} eq "true" ) 596 { 597 $lic_checkbox->set_active( $true ); 598 } 599 else { $lic_checkbox->set_active( $false ); } 600 601 $dialog2->set_title("Edit Server: $selected_machine"); 602 603 $dialog2->show_all(); 604} 605 606# handler for when a row is selected, grabs info from the selected row 607# looks the corresponding values up in the hash and 608# stuffs them into variables to be used in other subs 609sub list_sel_row 610{ 611 my $selection = ($list1->get_selected_indices)[0]; 612 my @row = @{(@{$list1->{data}})[$selection]}; 613 614 my $fs_tf; 615 my $bmp_tf; 616 $selected_machine = $row[0]; 617 $selected_machine_ip = $ip_hash{$selected_machine}; 618 $selected_uname = $uname_hash{$selected_machine}; 619 $selected_geom = $geom_hash{$selected_machine}; 620 $selected_fs = $fullscreen_hash{$selected_machine}; 621 $selected_bitmap_upd = $bitmap_upd_hash{$selected_machine}; 622 $selected_lic = $license_hash{$selected_machine}; 623 $selected_kmap = $kmap_hash{$selected_machine}; 624 $selected_kmap_hex = $kmap_trans_hash{$selected_kmap}; 625 $selected_passthru = $passthru_hash{$selected_machine}; 626 627 if( $selected_fs eq "true" ) { $fs_tf = "ON"; } 628 else { $fs_tf = "OFF"; } 629 if( $selected_bitmap_upd eq "true" ) { $bmp_tf = "Forcing Bitmap Updates"; } 630 else { $bmp_tf = "not Forcing Bitmap Updates"; } 631 print "You selected \"$selected_machine\", with the IP \"$selected_machine_ip\", Geometry is \"$selected_geom\"\nUsername is \"$selected_uname\", Fullscreen is $fs_tf, $bmp_tf\nKeyboard Mapping is \"$selected_kmap\"\n\n"; 632} 633 634sub list_exec_row { 635 return 1 unless $selected_machine_ip; 636 my ($w, $ev) = @_; 637 if ($ev->{type} eq '2button_press' and $ev->{button} == 1) { 638 # well, probably we should emulate proper signal marshalling 639 # for 'click' on the 'Connect' button, but for the moment it's 640 # enough to simply call 'rdesque_connect' 641 # list double-click patch by Alexey Morozov 642 &rdesque_connect; 643 } 644 return 1; 645} 646 647# fairly simple, just spits out a config file based on the 648# data contained in the hashes 649sub write_out_config 650{ 651 my $machina_p; 652 my @machines_p; 653 my $count = 1; 654 655 unlink( "$ENV{HOME}/.xrdesktop2_config" ); 656 # fixed by Ken Caruso 657 open( CONFIG, ">$ENV{HOME}/.xrdesktop2_config" ); 658 select( CONFIG ); 659 660 print "\# NO USER SERVICABLE PARTS HERE.\n# EXPERTS ONLY!!!\n"; 661 print "#\n\n"; 662 663 @machines_p = keys %ip_hash; 664 foreach $machina_p (sort @machines_p) 665 { 666 print "# Entry $count\n"; 667 print "Name=$machina_p\n"; 668 print "IP=$ip_hash{$machina_p}\n"; 669 print "Uname=$uname_hash{$machina_p}\n"; 670 print "Geometry=$geom_hash{$machina_p}\n"; 671 print "Fullscreen=$fullscreen_hash{$machina_p}\n"; 672 print "Bitmap_Updates=$bitmap_upd_hash{$machina_p}\n"; 673 print "Keymap=$kmap_hash{$machina_p}\n"; 674 print "NoReqLic=$license_hash{$machina_p}\n"; 675 print "Passthru=$passthru_hash{$machina_p}\n\n"; 676 $count++; 677 } 678 select( STDOUT ); 679 close( CONFIG ); 680} 681 682# does the actual adding of the server to the hash and config files 683# since the rdesque_add() sub just creates the dialog. 684# this is the one linked to the "ok" button in the add dialog 685sub do_add_server 686{ 687 my $name_added = $name_entry->get_text(); 688 my $ip_added = $ip_entry->get_text(); 689 my $uname_added = $uname_entry->get_text(); 690 my $reso = $combo1->entry->get_text(); 691 my $kmap = $combo2->entry->get_text(); 692 my $pthru = $passthru_entry->get_text(); 693 my $fs_state; 694 my $bmp_state; 695 my $lic_state; 696 697 if( $fs_checkbox->get_active ) {$fs_state = "true";} 698 else {$fs_state = "false";} 699 700 if( $bmp_checkbox->get_active ) {$bmp_state = "true";} 701 else {$bmp_state = "false";} 702 703 if( $lic_checkbox->get_active ) {$lic_state = "true";} 704 else {$lic_state = "false";} 705 706 chomp $name_added; 707 chomp $ip_added; 708 chomp $uname_added; 709 chomp $reso; 710 chomp $fs_state; 711 chomp $bmp_state; 712 chomp $lic_state; 713 chomp $kmap; 714 chomp $pthru; 715 716 my $check_dupe_key = exists $ip_hash{$name_added}; 717 if( $name_added ne "" && $ip_added ne "" && $check_dupe_key != $true ) 718 { 719 $ip_hash{$name_added} = $ip_added; 720 $uname_hash{$name_added} = $uname_added; 721 $geom_hash{$name_added} = $reso; 722 $fullscreen_hash{$name_added} = $fs_state; 723 $bitmap_upd_hash{$name_added} = $bmp_state; 724 $license_hash{$name_added} = $lic_state; 725 $kmap_hash{$name_added} = $kmap; 726 $passthru_hash{$name_added} = $pthru; 727# print "Adding: $name_added, $pthru\n"; 728 write_out_config(); 729# print "Added: name=$name_added, ip/hostname=$ip_added, username=$uname_added\nResolution=$reso, Fullscreen=$fs_state, Force Bitmap Updates=$bmp_state\nKeyboard Mapping=$kmap\n\n"; 730 $dialog1->destroy(); 731 populate_clist_from_config(); 732 } else { 733 my $field1; 734 my $doh_dialog = new Gtk2::Dialog(); 735 $doh_dialog->title("Err..."); 736 my $doh_ok = new Gtk2::Button( "Ok" ); 737 $doh_ok->signal_connect( "clicked", sub { $doh_dialog->destroy(); } ); 738 my $doh_label = new Gtk2::Label(); 739 if( $name_added eq "" ) 740 { 741 $field1 = "You left the Name field blank.\nConfig NOT updated"; 742 $doh_label->set_text( $field1 ); 743 } 744 elsif( $ip_added eq "" ) 745 { 746 $field1 = "You left the IP/Hostname field blank.\nConfig NOT updated"; 747 $doh_label->set_text( $field1 ); 748 } 749 elsif( $check_dupe_key ) 750 { 751 $doh_label->set_text( "An entry named \"$name_added\" already exists.\nPlease choose another name." ); 752 } 753 else 754 { 755 $field1 = "***CRITICAL ERROR***"; 756 $doh_label->set_text( $field1 ); 757 } 758 $doh_dialog->vbox->pack_start( $doh_label, $true, $true, 0 ); 759 $doh_dialog->action_area->pack_start( $doh_ok, $true, $true, 0 ); 760 $doh_dialog->show_all(); 761 } 762} 763 764# does the actual editing of the server in the hash and config 765# files since the rdesque_edit() sub just creates the dialog. 766# this is the one linked to the "ok button in the dialog 767sub do_edit_server 768{ 769 my $name_edited = $name_entry->get_text(); 770 my $ip_edited = $ip_entry->get_text(); 771 my $uname_edited = $uname_entry->get_text(); 772 my $pthru = $passthru_entry->get_text(); 773 my $reso = $combo1->entry->get_text(); 774 my $kmap = $combo2->entry->get_text(); 775 my $fs_state; 776 my $bmp_state; 777 my $lic_state; 778 779 if( $fs_checkbox->get_active ) {$fs_state = "true";} 780 else {$fs_state = "false";} 781 782 if( $bmp_checkbox->get_active ) {$bmp_state = "true";} 783 else {$bmp_state = "false";} 784 785 if( $lic_checkbox->get_active ) {$lic_state = "true";} 786 else {$lic_state = "false";} 787 788 chomp $name_edited; 789 chomp $ip_edited; 790 chomp $uname_edited; 791 chomp $reso; 792 chomp $fs_state; 793 chomp $bmp_state; 794 chomp $lic_state; 795 chomp $kmap; 796 chomp $pthru; 797 798 if( $name_edited ne "" && $ip_edited ne "" ) 799 { 800 my $old_name = $selected_machine; 801 my $old_ip = $ip_hash{$selected_machine}; 802 803 delete $ip_hash{$selected_machine}; 804 $ip_hash{$name_edited} = $ip_edited; 805 delete $uname_hash{$selected_machine}; 806 $uname_hash{$name_edited} = $uname_edited; 807 delete $geom_hash{$selected_machine}; 808 $geom_hash{$name_edited} = $reso; 809 delete $fullscreen_hash{$selected_machine}; 810 $fullscreen_hash{$name_edited} = $fs_state; 811 delete $bitmap_upd_hash{$selected_machine}; 812 $bitmap_upd_hash{$name_edited} = $bmp_state; 813 delete $license_hash{$selected_machine}; 814 $license_hash{$name_edited} = $lic_state; 815 delete $kmap_hash{$selected_machine}; 816 $kmap_hash{$name_edited} = $kmap; 817 delete $passthru_hash{$selected_machine}; 818 $passthru_hash{$name_edited} = $pthru; 819 820 write_out_config(); 821 print "Old data: name = $old_name, ip/hostname = $old_ip\n"; 822 print "New data: name = $name_edited, ip/hostname = $ip_edited\n"; 823 $dialog2->destroy(); 824 populate_clist_from_config(); 825 } else { 826 my $field1; 827 my $doh_dialog = new Gtk2::Dialog(); 828 $doh_dialog->title("Err..."); 829 my $doh_ok = new Gtk2::Button( "Ok" ); 830 $doh_ok->signal_connect( "clicked", sub { $doh_dialog->destroy(); } ); 831 if( $name_edited eq "" ) { $field1 = "Name"; } 832 elsif( $ip_edited eq "" ) { $field1 = "IP/Hostname"; } 833 else { $field1 = "***CRITICAL ERROR***"; } 834 my $doh_label = new Gtk2::Label( "You left the $field1 field blank.\nConfig NOT updated." ); 835 836 $doh_dialog->vbox->pack_start( $doh_label, $true, $true, 0 ); 837 $doh_dialog->action_area->pack_start( $doh_ok, $true, $true, 0 ); 838 $doh_dialog->show_all(); 839 } 840} 841 842# reads in the config file (~/.xrdesktop_config by default) 843# plugs all the data into a hash ($ip_hash) and 844# sets up the $list1 widget with the data in the hash 845sub populate_clist_from_config 846{ 847 unless( -e "$ENV{HOME}/.xrdesktop2_config") { write_out_config();} 848 849 open( CONFIG, "$ENV{HOME}/.xrdesktop2_config"); 850 while( <CONFIG> ) 851 { 852 853 # ignore comments and blank lines 854 next if /^#/; 855 next if /^$/; 856 857 # get me some data 858 $raw_data = $_; 859 chomp $raw_data; 860 ( $field_type, $field_data ) = split /=/, $raw_data,2; 861 chomp $field_type; 862 chomp $field_data; 863 864 # stuff the first line (hopefully Name) into vars 865 if( $field_type eq "Name" ) {$machine_name = $field_data;} 866 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 867 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 868 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 869 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 870 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 871 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 872 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 873 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 874 else {print "Bad Data: $field_type : $field_data\n";} 875 876 # stuff the second line (hopefully IP) into vars 877 $raw_data = <CONFIG>; 878 chomp $raw_data; 879 ( $field_type, $field_data ) = split /=/, $raw_data,2; 880 chomp $field_type; 881 chomp $field_data; 882 if( $field_type eq "Name" ) {$machine_name = $field_data;} 883 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 884 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 885 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 886 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 887 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 888 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 889 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 890 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 891 else {print "Bad Data: $field_type : $field_data\n";} 892 893 # stuff the third line (hopefully Uname) into vars 894 $raw_data = <CONFIG>; 895 chomp $raw_data; 896 ( $field_type, $field_data ) = split /=/, $raw_data,2; 897 chomp $field_type; 898 chomp $field_data; 899 if( $field_type eq "Name" ) {$machine_name = $field_data;} 900 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 901 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 902 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 903 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 904 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 905 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 906 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 907 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 908 else {print "Bad Data: $field_type : $field_data\n";} 909 910 # stuff the fourth line (hopefully Geometry) into vars 911 $raw_data = <CONFIG>; 912 chomp $raw_data; 913 ( $field_type, $field_data ) = split /=/, $raw_data,2; 914 chomp $field_type; 915 chomp $field_data; 916 if( $field_type eq "Name" ) {$machine_name = $field_data;} 917 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 918 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 919 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 920 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 921 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 922 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 923 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 924 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 925 else {print "Bad Data: $field_type : $field_data\n";} 926 927 # stuff the fifth line (hopefully Fullscreen) into vars 928 $raw_data = <CONFIG>; 929 chomp $raw_data; 930 ( $field_type, $field_data ) = split /=/, $raw_data,2; 931 chomp $field_type; 932 chomp $field_data; 933 if( $field_type eq "Name" ) {$machine_name = $field_data;} 934 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 935 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 936 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 937 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 938 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 939 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 940 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 941 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 942 else {print "Bad Data: $field_type : $field_data\n";} 943 944 # stuff the sixth line (hopefully Bitmap_Updates) into vars 945 $raw_data = <CONFIG>; 946 chomp $raw_data; 947 ( $field_type, $field_data ) = split /=/, $raw_data,2; 948 chomp $field_type; 949 chomp $field_data; 950 if( $field_type eq "Name" ) {$machine_name = $field_data;} 951 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 952 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 953 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 954 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 955 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 956 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 957 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 958 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 959 else {print "Bad Data: $field_type : $field_data\n";} 960 961 # stuff the seventh line (hopefully Keymap) into vars 962 $raw_data = <CONFIG>; 963 chomp $raw_data; 964 ( $field_type, $field_data ) = split /=/, $raw_data,2; 965 chomp $field_type; 966 chomp $field_data; 967 if( $field_type eq "Name" ) {$machine_name = $field_data;} 968 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 969 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 970 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 971 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 972 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 973 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 974 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 975 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 976 else {print "Bad Data: $field_type : $field_data\n";} 977 978 # stuff the eighth line (hopefully NoReqLic) into vars 979 $raw_data = <CONFIG>; 980 chomp $raw_data; 981 ( $field_type, $field_data ) = split /=/, $raw_data,2; 982 chomp $field_type; 983 chomp $field_data; 984 if( $field_type eq "Name" ) {$machine_name = $field_data;} 985 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 986 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 987 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 988 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 989 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 990 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 991 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 992 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 993 else {print "Bad Data: $field_type : $field_data\n";} 994 995 # stuff the ninth line (hopefully Passthru) into vars 996 $raw_data = <CONFIG>; 997 chomp $raw_data; 998 ( $field_type, $field_data ) = split /=/, $raw_data,2; 999 chomp $field_type; 1000 chomp $field_data; 1001 if( $field_type eq "Name" ) {$machine_name = $field_data;} 1002 elsif( $field_type eq "IP" ) {$machine_ip = $field_data;} 1003 elsif( $field_type eq "Uname" ) {$machine_uname = $field_data;} 1004 elsif( $field_type eq "Geometry" ) { $machine_geom = $field_data;} 1005 elsif( $field_type eq "Fullscreen" ) {$machine_fs = $field_data;} 1006 elsif( $field_type eq "Bitmap_Updates" ) {$machine_bitmap_upd = $field_data;} 1007 elsif( $field_type eq "Keymap" ) {$machine_kmap = $field_data;} 1008 elsif( $field_type eq "NoReqLic" ) {$machine_lic = $field_data;} 1009 elsif( $field_type eq "Passthru" ) {$machine_passthru = $field_data;} 1010 else {print "Bad Data: $field_type : $field_data\n";} 1011 1012 # finally, stuff it all into the hashes 1013 chomp $machine_name; 1014 chomp $machine_ip; 1015 chomp $machine_uname; 1016 chomp $machine_geom; 1017 chomp $machine_fs; 1018 chomp $machine_bitmap_upd; 1019 chomp $machine_kmap; 1020 chomp $machine_passthru; 1021 $ip_hash{$machine_name} = $machine_ip; 1022 $uname_hash{$machine_name} = $machine_uname; 1023 $geom_hash{$machine_name} = $machine_geom; 1024 $fullscreen_hash{$machine_name} = $machine_fs; 1025 $bitmap_upd_hash{$machine_name} = $machine_bitmap_upd; 1026 $license_hash{$machine_name} = $machine_lic; 1027 $kmap_hash{$machine_name} = $machine_kmap; 1028 $passthru_hash{$machine_name} = $machine_passthru; 1029 } 1030 close CONFIG; 1031 1032 # and last, but not least, stuff it all into the clist 1033 for (my $n=$indexmax-1; $n>=0; $n--) 1034 { 1035 splice @{ $list1->{data} }, $n, 1; 1036 } 1037 @machines = keys %ip_hash; 1038 $indexmax = 0; 1039 foreach $machina (sort @machines) 1040 { 1041 push @{$list1->{data}}, [$machina, $ip_hash{$machina}, $uname_hash{$machina}, $kmap_hash{$machina}, $geom_hash{$machina}, $fullscreen_hash{$machina}, $bitmap_upd_hash{$machina}, $license_hash{$machina}, $passthru_hash{$machina} ]; 1042 $indexmax++; 1043 } 1044} 1045