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

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