root/source4/client/tree.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. error_message
  2. get_path
  3. make_tree_data
  4. cb_select_child
  5. cb_unselect_child
  6. cb_itemsignal
  7. cb_selection_changed
  8. cb_wholenet
  9. auth_fn
  10. main

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    SMB client GTK+ tree-based application
   4    Copyright (C) Andrew Tridgell 1998
   5    Copyright (C) Richard Sharpe 2001
   6    Copyright (C) John Terpstra 2001
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 /* example-gtk+ application, ripped off from the gtk+ tree.c sample */
  23 
  24 #include <stdio.h>
  25 #include <errno.h>
  26 #include <gtk/gtk.h>
  27 #include "libsmbclient.h"
  28 
  29 static GtkWidget *clist;
  30 
  31 struct tree_data {
  32 
  33   guint32 type;    /* Type of tree item, an SMBC_TYPE */
  34   char name[256];  /* May need to change this later   */
  35 
  36 };
  37 
  38 void error_message(gchar *message) {
     /* [<][>][^][v][top][bottom][index][help] */
  39 
  40   GtkWidget *dialog, *label, *okay_button;
  41      
  42   /* Create the widgets */
  43      
  44   dialog = gtk_dialog_new();
  45   gtk_window_set_modal(GTK_WINDOW(dialog), True);
  46   label = gtk_label_new (message);
  47   okay_button = gtk_button_new_with_label("Okay");
  48      
  49   /* Ensure that the dialog box is destroyed when the user clicks ok. */
  50      
  51   gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
  52                              GTK_SIGNAL_FUNC (gtk_widget_destroy), dialog);
  53   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
  54                      okay_button);
  55 
  56   /* Add the label, and show everything we've added to the dialog. */
  57 
  58   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
  59                      label);
  60   gtk_widget_show_all (dialog);
  61 }
  62 
  63 /*
  64  * We are given a widget, and we want to retrieve its URL so we 
  65  * can do a directory listing.
  66  *
  67  * We walk back up the tree, picking up pieces until we hit a server or
  68  * workgroup type and return a path from there
  69  */
  70 
  71 static char path_string[1024];
  72 
  73 char *get_path(GtkWidget *item)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75   GtkWidget *p = item;
  76   struct tree_data *pd;
  77   char *comps[1024];  /* We keep pointers to the components here */
  78   int i = 0, j, level,type;
  79 
  80   /* Walk back up the tree, getting the private data */
  81 
  82   level = GTK_TREE(item->parent)->level;
  83 
  84   /* Pick up this item's component info */
  85 
  86   pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(item));
  87 
  88   comps[i++] = pd->name;
  89   type = pd->type;
  90 
  91   while (level > 0 && type != SMBC_SERVER && type != SMBC_WORKGROUP) {
  92 
  93     /* Find the parent and extract the data etc ... */
  94 
  95     p = GTK_WIDGET(p->parent);    
  96     p = GTK_WIDGET(GTK_TREE(p)->tree_owner);
  97 
  98     pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(p));
  99 
 100     level = GTK_TREE(item->parent)->level;
 101 
 102     comps[i++] = pd->name;
 103     type = pd->type;
 104 
 105   }
 106 
 107   /* 
 108    * Got a list of comps now, should check that we did not hit a workgroup
 109    * when we got other things as well ... Later
 110    *
 111    * Now, build the path
 112    */
 113 
 114   snprintf(path_string, sizeof(path_string), "smb:/");
 115 
 116   for (j = i - 1; j >= 0; j--) {
 117 
 118     strncat(path_string, "/", sizeof(path_string) - strlen(path_string));
 119     strncat(path_string, comps[j], sizeof(path_string) - strlen(path_string));
 120 
 121   }
 122   
 123   fprintf(stdout, "Path string = %s\n", path_string);
 124 
 125   return path_string;
 126 
 127 }
 128 
 129 struct tree_data *make_tree_data(guint32 type, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 130 {
 131   struct tree_data *p = malloc_p(struct tree_data);
 132 
 133   if (p) {
 134 
 135     p->type = type;
 136     strncpy(p->name, name, sizeof(p->name));
 137 
 138   }
 139 
 140   return p;
 141 
 142 }
 143 
 144 /* Note that this is called every time the user clicks on an item,
 145    whether it is already selected or not. */
 146 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
     /* [<][>][^][v][top][bottom][index][help] */
 147                              GtkWidget *subtree)
 148 {
 149   gint dh, err, dirlen;
 150   char dirbuf[512];
 151   struct smbc_dirent *dirp;
 152   struct stat st1;
 153   char path[1024], path1[1024];
 154 
 155   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
 156            root_tree, subtree, child);
 157 
 158   /* Now, figure out what it is, and display it in the clist ... */
 159 
 160   gtk_clist_clear(GTK_CLIST(clist));  /* Clear the CLIST */
 161 
 162   /* Now, get the private data for the subtree */
 163 
 164   strncpy(path, get_path(child), 1024);
 165 
 166   if ((dh = smbc_opendir(path)) < 0) { /* Handle error */
 167 
 168     g_print("cb_select_child: Could not open dir %s, %s\n", path,
 169             strerror(errno));
 170 
 171     gtk_main_quit();
 172 
 173     return;
 174 
 175   }
 176 
 177   while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
 178                               sizeof(dirbuf))) != 0) {
 179 
 180     if (err < 0) {
 181 
 182       g_print("cb_select_child: Could not read dir %s, %s\n", path,
 183               strerror(errno));
 184 
 185       gtk_main_quit();
 186 
 187       return;
 188 
 189     }
 190 
 191     dirp = (struct smbc_dirent *)dirbuf;
 192 
 193     while (err > 0) {
 194       gchar col1[128], col2[128], col3[128], col4[128];
 195       gchar *rowdata[4] = {col1, col2, col3, col4};
 196 
 197       dirlen = dirp->dirlen;
 198 
 199       /* Format each of the items ... */
 200 
 201       strncpy(col1, dirp->name, 128);
 202 
 203       col2[0] = col3[0] = col4[0] = (char)0;
 204 
 205       switch (dirp->smbc_type) {
 206 
 207       case SMBC_WORKGROUP:
 208 
 209         break;
 210 
 211       case SMBC_SERVER:
 212 
 213         strncpy(col2, (dirp->comment?dirp->comment:""), 128);
 214 
 215         break;
 216 
 217       case SMBC_FILE_SHARE:
 218 
 219         strncpy(col2, (dirp->comment?dirp->comment:""), 128);
 220 
 221         break;
 222 
 223       case SMBC_PRINTER_SHARE:
 224 
 225         strncpy(col2, (dirp->comment?dirp->comment:""), 128);
 226         break;
 227 
 228       case SMBC_COMMS_SHARE:
 229 
 230         break;
 231 
 232       case SMBC_IPC_SHARE:
 233 
 234         break;
 235 
 236       case SMBC_DIR:
 237       case SMBC_FILE:
 238 
 239         /* Get stats on the file/dir and see what we have */
 240 
 241         if (!ISDOT(dirp->name) && !ISDOTDOT(dirp->name)) {
 242 
 243           strncpy(path1, path, sizeof(path1));
 244           strncat(path1, "/", sizeof(path) - strlen(path));
 245           strncat(path1, dirp->name, sizeof(path) - strlen(path));
 246 
 247           if (smbc_stat(path1, &st1) < 0) {
 248             
 249             if (errno != EBUSY) {
 250               
 251               g_print("cb_select_child: Could not stat file %s, %s\n", path1, 
 252                       strerror(errno));
 253             
 254               gtk_main_quit();
 255 
 256               return;
 257 
 258             }
 259             else {
 260 
 261               strncpy(col2, "Device or resource busy", sizeof(col2));
 262 
 263             }
 264           }
 265           else {
 266             /* Now format each of the relevant things ... */
 267 
 268             snprintf(col2, sizeof(col2), "%c%c%c%c%c%c%c%c%c(%0X)",
 269                      (st1.st_mode&S_IRUSR?'r':'-'),
 270                      (st1.st_mode&S_IWUSR?'w':'-'),
 271                      (st1.st_mode&S_IXUSR?'x':'-'),
 272                      (st1.st_mode&S_IRGRP?'r':'-'),
 273                      (st1.st_mode&S_IWGRP?'w':'-'),
 274                      (st1.st_mode&S_IXGRP?'x':'-'),
 275                      (st1.st_mode&S_IROTH?'r':'-'),
 276                      (st1.st_mode&S_IWOTH?'w':'-'),
 277                      (st1.st_mode&S_IXOTH?'x':'-'),
 278                      st1.st_mode); 
 279             snprintf(col3, sizeof(col3), "%u", st1.st_size);
 280             snprintf(col4, sizeof(col4), "%s", ctime(&st1.st_mtime));
 281           }
 282         }
 283 
 284         break;
 285 
 286       default:
 287 
 288         break;
 289       }
 290 
 291       gtk_clist_append(GTK_CLIST(clist), rowdata);
 292 
 293       (char *)dirp += dirlen;
 294       err -= dirlen;
 295 
 296     }
 297 
 298   }
 299 
 300 }
 301 
 302 /* Note that this is never called */
 303 static void cb_unselect_child( GtkWidget *root_tree,
     /* [<][>][^][v][top][bottom][index][help] */
 304                                GtkWidget *child,
 305                                GtkWidget *subtree )
 306 {
 307   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
 308            root_tree, subtree, child);
 309 }
 310 
 311 /* for all the GtkItem:: and GtkTreeItem:: signals */
 312 static void cb_itemsignal( GtkWidget *item,
     /* [<][>][^][v][top][bottom][index][help] */
 313                            gchar     *signame )
 314 {
 315   GtkWidget *real_tree, *aitem, *subtree;
 316   gchar *name;
 317   GtkLabel *label;
 318   gint dh, err, dirlen, level;
 319   char dirbuf[512];
 320   struct smbc_dirent *dirp;
 321   
 322   label = GTK_LABEL (GTK_BIN (item)->child);
 323   /* Get the text of the label */
 324   gtk_label_get (label, &name);
 325 
 326   level = GTK_TREE(item->parent)->level;
 327 
 328   /* Get the level of the tree which the item is in */
 329   g_print ("%s called for item %s->%p, level %d\n", signame, name,
 330            item, GTK_TREE (item->parent)->level);
 331 
 332   real_tree = GTK_TREE_ITEM_SUBTREE(item);  /* Get the subtree */
 333 
 334   if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
 335     char server[128];
 336 
 337     if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */
 338       gchar errmsg[256];
 339 
 340       g_print("cb_itemsignal: Could not open dir %s, %s\n", get_path(item), 
 341               strerror(errno));
 342 
 343       slprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not open dir %s, %s\n", get_path(item), strerror(errno));
 344 
 345       error_message(errmsg);
 346 
 347       /*      gtk_main_quit();*/
 348 
 349       return;
 350 
 351     }
 352 
 353     while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 
 354                                 sizeof(dirbuf))) != 0) {
 355 
 356       if (err < 0) { /* An error, report it */
 357         gchar errmsg[256];
 358 
 359         g_print("cb_itemsignal: Could not read dir smbc://, %s\n",
 360                 strerror(errno));
 361 
 362         slprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not read dir smbc://, %s\n", strerror(errno));
 363 
 364         error_message(errmsg);
 365 
 366         /*      gtk_main_quit();*/
 367 
 368         return;
 369 
 370       }
 371 
 372       dirp = (struct smbc_dirent *)dirbuf;
 373 
 374       while (err > 0) {
 375         struct tree_data *my_data;
 376 
 377         dirlen = dirp->dirlen;
 378 
 379         my_data = make_tree_data(dirp->smbc_type, dirp->name);
 380 
 381         if (!my_data) {
 382 
 383           g_print("Could not allocate space for tree_data: %s\n",
 384                   dirp->name);
 385 
 386           gtk_main_quit();
 387           return;
 388 
 389         }
 390 
 391         aitem = gtk_tree_item_new_with_label(dirp->name);
 392 
 393         /* Connect all GtkItem:: and GtkTreeItem:: signals */
 394         gtk_signal_connect (GTK_OBJECT(aitem), "select",
 395                             GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 396         gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
 397                             GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 398         gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
 399                             GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 400         gtk_signal_connect (GTK_OBJECT(aitem), "expand",
 401                             GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
 402         gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
 403                             GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
 404         /* Add it to the parent tree */
 405         gtk_tree_append (GTK_TREE(real_tree), aitem);
 406 
 407         gtk_widget_show (aitem);
 408 
 409         gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
 410 
 411         fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
 412 
 413         if (dirp->smbc_type != SMBC_FILE &&
 414             dirp->smbc_type != SMBC_IPC_SHARE &&
 415             (!ISDOT(dirp->name)) &&
 416             (!ISDOTDOT(dirp->name))){
 417           
 418           subtree = gtk_tree_new();
 419           gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
 420 
 421           gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
 422                              GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 423           gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
 424                              GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 425 
 426         }
 427 
 428         (char *)dirp += dirlen;
 429         err -= dirlen;
 430 
 431       }
 432 
 433     }
 434 
 435     smbc_closedir(dh);   
 436 
 437   }
 438   else if (strncmp(signame, "collapse", 8) == 0) {
 439     GtkWidget *subtree = gtk_tree_new();
 440 
 441     gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children);
 442 
 443     gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 444 
 445     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 446                         GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 447     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 448                         GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 449 
 450   }
 451 
 452 }
 453 
 454 static void cb_selection_changed( GtkWidget *tree )
     /* [<][>][^][v][top][bottom][index][help] */
 455 {
 456   GList *i;
 457   
 458   g_print ("selection_change called for tree %p\n", tree);
 459   g_print ("selected objects are:\n");
 460 
 461   i = GTK_TREE_SELECTION(tree);
 462   while (i){
 463     gchar *name;
 464     GtkLabel *label;
 465     GtkWidget *item;
 466 
 467     /* Get a GtkWidget pointer from the list node */
 468     item = GTK_WIDGET (i->data);
 469     label = GTK_LABEL (GTK_BIN (item)->child);
 470     gtk_label_get (label, &name);
 471     g_print ("\t%s on level %d\n", name, GTK_TREE
 472              (item->parent)->level);
 473     i = i->next;
 474   }
 475 }
 476 
 477 /*
 478  * Expand or collapse the whole network ...
 479  */
 480 static void cb_wholenet(GtkWidget *item, gchar *signame)
     /* [<][>][^][v][top][bottom][index][help] */
 481 {
 482   GtkWidget *real_tree, *aitem, *subtree;
 483   gchar *name;
 484   GtkLabel *label;
 485   gint dh, err, dirlen;
 486   char dirbuf[512];
 487   struct smbc_dirent *dirp;
 488   
 489   label = GTK_LABEL (GTK_BIN (item)->child);
 490   gtk_label_get (label, &name);
 491   g_print ("%s called for item %s->%p, level %d\n", signame, name,
 492            item, GTK_TREE (item->parent)->level);
 493 
 494   real_tree = GTK_TREE_ITEM_SUBTREE(item);  /* Get the subtree */
 495 
 496   if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
 497 
 498     if ((dh = smbc_opendir("smb://")) < 0) { /* Handle error */
 499 
 500       g_print("cb_wholenet: Could not open dir smbc://, %s\n",
 501               strerror(errno));
 502 
 503       gtk_main_quit();
 504 
 505       return;
 506 
 507     }
 508 
 509     while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 
 510                                 sizeof(dirbuf))) != 0) {
 511 
 512       if (err < 0) { /* An error, report it */
 513 
 514         g_print("cb_wholenet: Could not read dir smbc://, %s\n",
 515                 strerror(errno));
 516 
 517         gtk_main_quit();
 518 
 519         return;
 520 
 521       }
 522 
 523       dirp = (struct smbc_dirent *)dirbuf;
 524 
 525       while (err > 0) {
 526         struct tree_data *my_data;
 527 
 528         dirlen = dirp->dirlen;
 529 
 530         my_data = make_tree_data(dirp->smbc_type, dirp->name);
 531 
 532         aitem = gtk_tree_item_new_with_label(dirp->name);
 533 
 534         /* Connect all GtkItem:: and GtkTreeItem:: signals */
 535         gtk_signal_connect (GTK_OBJECT(aitem), "select",
 536                             GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 537         gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
 538                             GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 539         gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
 540                             GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 541         gtk_signal_connect (GTK_OBJECT(aitem), "expand",
 542                             GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
 543         gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
 544                             GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
 545 
 546         gtk_tree_append (GTK_TREE(real_tree), aitem);
 547         /* Show it - this can be done at any time */
 548         gtk_widget_show (aitem);
 549 
 550         gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
 551 
 552         fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
 553 
 554         subtree = gtk_tree_new();
 555 
 556         gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
 557 
 558         gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
 559                            GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 560         gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
 561                            GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 562 
 563         (char *)dirp += dirlen;
 564         err -= dirlen;
 565 
 566       }
 567 
 568     }
 569 
 570     smbc_closedir(dh);   
 571 
 572   }
 573   else { /* Must be collapse ... FIXME ... */
 574     GtkWidget *subtree = gtk_tree_new();
 575 
 576     gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children);
 577 
 578     gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 579 
 580     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 581                         GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 582     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 583                         GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 584 
 585 
 586   }
 587 
 588 }
 589 
 590 /* Should put up a dialog box to ask the user for username and password */
 591 
 592 static void 
 593 auth_fn(const char *server, const char *share,
     /* [<][>][^][v][top][bottom][index][help] */
 594         char *workgroup, int wgmaxlen, char *username, int unmaxlen,
 595         char *password, int pwmaxlen)
 596 {
 597 
 598    strncpy(username, "test", unmaxlen);
 599    strncpy(password, "test", pwmaxlen);
 600 
 601 }
 602 
 603 static char *col_titles[] = {
 604   "Name", "Attributes", "Size", "Modification Date",
 605 };
 606 
 607 int main( int   argc,
     /* [<][>][^][v][top][bottom][index][help] */
 608           char *argv[] )
 609 {
 610   GtkWidget *window, *scrolled_win, *scrolled_win2, *tree;
 611   GtkWidget *subtree, *item, *main_hbox, *r_pane, *l_pane;
 612   gint err, dh;
 613   gint i;
 614   char dirbuf[512];
 615   struct smbc_dirent *dirp;
 616 
 617   gtk_init (&argc, &argv);
 618 
 619   /* Init the smbclient library */
 620 
 621   err = smbc_init(auth_fn, 10);
 622 
 623   /* Print an error response ... */
 624 
 625   if (err < 0) {
 626 
 627     fprintf(stderr, "smbc_init returned %s (%i)\nDo you have a ~/.smb/smb.conf file?\n", strerror(errno), errno);
 628     exit(1);
 629 
 630   }
 631 
 632   /* a generic toplevel window */
 633   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 634   gtk_widget_set_name(window, "main browser window");
 635   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
 636                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
 637   gtk_window_set_title(GTK_WINDOW(window), "The Linux Windows Network Browser");
 638   gtk_widget_set_usize(GTK_WIDGET(window), 750, -1);
 639   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
 640 
 641   gtk_widget_show (window);
 642 
 643   /* A container for the two panes ... */
 644 
 645   main_hbox = gtk_hbox_new(FALSE, 1);
 646   gtk_container_border_width(GTK_CONTAINER(main_hbox), 1);
 647   gtk_container_add(GTK_CONTAINER(window), main_hbox);
 648 
 649   gtk_widget_show(main_hbox);
 650 
 651   l_pane = gtk_hpaned_new();
 652   gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
 653   r_pane = gtk_hpaned_new();
 654   gtk_paned_gutter_size(GTK_PANED(r_pane), (GTK_PANED(r_pane))->handle_size);
 655   gtk_container_add(GTK_CONTAINER(main_hbox), l_pane);
 656   gtk_widget_show(l_pane);
 657 
 658   /* A generic scrolled window */
 659   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
 660   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
 661                                   GTK_POLICY_AUTOMATIC,
 662                                   GTK_POLICY_AUTOMATIC);
 663   gtk_widget_set_usize (scrolled_win, 150, 200);
 664   gtk_container_add (GTK_CONTAINER(l_pane), scrolled_win);
 665   gtk_widget_show (scrolled_win);
 666 
 667   /* Another generic scrolled window */
 668   scrolled_win2 = gtk_scrolled_window_new (NULL, NULL);
 669   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win2),
 670                                   GTK_POLICY_AUTOMATIC,
 671                                   GTK_POLICY_AUTOMATIC);
 672   gtk_widget_set_usize (scrolled_win2, 150, 200);
 673   gtk_paned_add2 (GTK_PANED(l_pane), scrolled_win2);
 674   gtk_widget_show (scrolled_win2);
 675   
 676   /* Create the root tree */
 677   tree = gtk_tree_new();
 678   g_print ("root tree is %p\n", tree);
 679   /* connect all GtkTree:: signals */
 680   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
 681                       GTK_SIGNAL_FUNC(cb_select_child), tree);
 682   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
 683                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
 684   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
 685                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
 686   /* Add it to the scrolled window */
 687   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
 688                                          tree);
 689   /* Set the selection mode */
 690   gtk_tree_set_selection_mode (GTK_TREE(tree),
 691                                GTK_SELECTION_MULTIPLE);
 692   /* Show it */
 693   gtk_widget_show (tree);
 694 
 695   /* Now, create a clist and attach it to the second pane */
 696 
 697   clist = gtk_clist_new_with_titles(4, col_titles);
 698 
 699   gtk_container_add (GTK_CONTAINER(scrolled_win2), clist);
 700 
 701   gtk_widget_show(clist);
 702 
 703   /* Now, build the top level display ... */
 704 
 705   if ((dh = smbc_opendir("smb:///")) < 0) {
 706 
 707     fprintf(stderr, "Could not list default workgroup: smb:///: %s\n",
 708             strerror(errno));
 709 
 710     exit(1);
 711 
 712   }
 713 
 714   /* Create a tree item for Whole Network */
 715 
 716   item = gtk_tree_item_new_with_label ("Whole Network");
 717   /* Connect all GtkItem:: and GtkTreeItem:: signals */
 718   gtk_signal_connect (GTK_OBJECT(item), "select",
 719                       GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 720   gtk_signal_connect (GTK_OBJECT(item), "deselect",
 721                       GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 722   gtk_signal_connect (GTK_OBJECT(item), "toggle",
 723                       GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 724   gtk_signal_connect (GTK_OBJECT(item), "expand",
 725                       GTK_SIGNAL_FUNC(cb_wholenet), "expand");
 726   gtk_signal_connect (GTK_OBJECT(item), "collapse",
 727                       GTK_SIGNAL_FUNC(cb_wholenet), "collapse");
 728   /* Add it to the parent tree */
 729   gtk_tree_append (GTK_TREE(tree), item);
 730   /* Show it - this can be done at any time */
 731   gtk_widget_show (item);
 732 
 733   subtree = gtk_tree_new();  /* A subtree for Whole Network */
 734 
 735   gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 736 
 737   gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 738                       GTK_SIGNAL_FUNC(cb_select_child), tree);
 739   gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 740                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
 741 
 742   /* Now, get the items in smb:/// and add them to the tree */
 743 
 744   dirp = (struct smbc_dirent *)dirbuf;
 745 
 746   while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 
 747                               sizeof(dirbuf))) != 0) {
 748 
 749     if (err < 0) { /* Handle the error */
 750 
 751       fprintf(stderr, "Could not read directory for smbc:///: %s\n",
 752               strerror(errno));
 753 
 754       exit(1);
 755 
 756     }
 757 
 758     fprintf(stdout, "Dir len: %u\n", err);
 759 
 760     while (err > 0) { /* Extract each entry and make a sub-tree */
 761       struct tree_data *my_data;
 762       int dirlen = dirp->dirlen;
 763 
 764       my_data = make_tree_data(dirp->smbc_type, dirp->name);
 765 
 766       item = gtk_tree_item_new_with_label(dirp->name);
 767       /* Connect all GtkItem:: and GtkTreeItem:: signals */
 768       gtk_signal_connect (GTK_OBJECT(item), "select",
 769                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 770       gtk_signal_connect (GTK_OBJECT(item), "deselect",
 771                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 772       gtk_signal_connect (GTK_OBJECT(item), "toggle",
 773                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 774       gtk_signal_connect (GTK_OBJECT(item), "expand",
 775                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
 776       gtk_signal_connect (GTK_OBJECT(item), "collapse",
 777                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
 778       /* Add it to the parent tree */
 779       gtk_tree_append (GTK_TREE(tree), item);
 780       /* Show it - this can be done at any time */
 781       gtk_widget_show (item);
 782 
 783       gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)my_data);
 784 
 785       fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
 786 
 787       subtree = gtk_tree_new();
 788 
 789       gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 790 
 791       gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 792                           GTK_SIGNAL_FUNC(cb_select_child), tree);
 793       gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 794                           GTK_SIGNAL_FUNC(cb_unselect_child), tree);
 795 
 796       (char *)dirp += dirlen;
 797       err -= dirlen;
 798 
 799     }
 800 
 801   }
 802 
 803   smbc_closedir(dh); /* FIXME, check for error :-) */
 804 
 805   /* Show the window and loop endlessly */
 806   gtk_main();
 807   return 0;
 808 }
 809 /* example-end */

/* [<][>][^][v][top][bottom][index][help] */