📄 tree.c
字号:
/* * Compaq Hot Plug Controller Graphical User Interface * Copyright 2000, 2001 Compaq Computer Corporation * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Please send all questions or concerns to linuxhotplug@compaq.com */#include "commonheader.h"#include "tree.h"#include "build_tree.h"#include "style.h"#include "kudzu-support.h"GtkCTreeNode* root_nodes[MAXSLOTS];char root_paths[MAXSLOTS][MAXLEN];int root_paths_size;GdkPixmap *card_icon, *att_status_on_icon, *att_status_off_icon; GdkBitmap *card_icon_mask, *att_status_on_icon_mask, *att_status_off_icon_mask; // define priority arrays using position->type relation (0-based array)// type 0 = slot, type 1 = bus, type 2 = function, type 3 = adapterint bus_based[] = {2,4,1,3};int slot_based[] = {4,1,2,3};int adapter_based[] = {3,1,2,4};int function_based[] = {2,1,4,3};void allocate_colors();void render_node(GtkCTree* tree, GtkCTreeNode* node, gpointer data);static void walk_general_layer_recurse(GtkCTree* tree, char* dir, GtkCTreeNode* parent); void build_from_slot(GtkCTree* tree, int index);int is_driverloaded(const char* name);// Define colorsGdkColor red = {0, 0xffff, 0x0000, 0x0000};GdkColor blue = {0, 0x0000, 0x0000, 0xffff};GdkColor green = {0, 0x0000, 0x8b00, 0x0000};GdkColor yellow = {0, 0xffff, 0xffff, 0x0000};GdkColor purple = {0, 0xffff, 0x0000, 0xffff};GdkColor orange = {0, 0xffff, 0x9999, 0x0000};GdkColor cyan = {0, 0x0000, 0xffff, 0xffff};GdkColor black = {0, 0x0000, 0x0000, 0x0000};GdkColor white = {0, 0xffff, 0xffff, 0xffff};GdkColor gray = {0, 0x1111, 0x1111, 0x1111};GdkColor light_gray = {0, 0xbd00, 0xbd00, 0xbd00};void allocate_colors(){ gdk_color_alloc (gdk_colormap_get_system (), &red); gdk_color_alloc (gdk_colormap_get_system (), &blue); gdk_color_alloc (gdk_colormap_get_system (), &green); gdk_color_alloc (gdk_colormap_get_system (), &yellow); gdk_color_alloc (gdk_colormap_get_system (), &purple); gdk_color_alloc (gdk_colormap_get_system (), &orange); gdk_color_alloc (gdk_colormap_get_system (), &cyan); gdk_color_alloc (gdk_colormap_get_system (), &black); gdk_color_alloc (gdk_colormap_get_system (), &white); gdk_color_alloc (gdk_colormap_get_system (), &gray); gdk_color_alloc (gdk_colormap_get_system (), &light_gray);}void load_pixmaps(GtkCTree* tree){ char *card_icon_path, *att_status_on_path, *att_status_off_path; GtkStyle* style = gtk_widget_get_style((GtkWidget*)tree); card_icon_path = gnome_pixmap_file("hotplug/card_icon.xpm"); att_status_on_path = gnome_pixmap_file("hotplug/enable_on.xpm"); att_status_off_path = gnome_pixmap_file("hotplug/enable_off.xpm"); card_icon = gdk_pixmap_create_from_xpm(g_window->window, &card_icon_mask, &style->bg[GTK_STATE_SELECTED], card_icon_path); att_status_on_icon = gdk_pixmap_create_from_xpm(g_window->window, &att_status_on_icon_mask, &style->bg[GTK_STATE_SELECTED], att_status_on_path); att_status_off_icon = gdk_pixmap_create_from_xpm(g_window->window, &att_status_off_icon_mask, &style->bg[GTK_STATE_SELECTED], att_status_off_path); if (card_icon_path) g_free(card_icon_path); if (att_status_on_path) g_free(att_status_on_path); if (att_status_off_path) g_free(att_status_off_path);}void set_back_pointer(GtkCTree* tree, GtkCTreeNode* node, gpointer data){ static public_adapter_info* curr_adapter = NULL; pci_tree_node* p_node = (pci_tree_node*) gtk_ctree_node_get_row_data(tree, node); while (p_node) { switch (p_node->type) { case 2: // function { public_function_info* function_p_node = (public_function_info*) p_node->node_info; if (!function_p_node->is_bridge) { if (curr_adapter) { curr_adapter->function = function_p_node; curr_adapter = NULL; } } } break; case 3: // adapter { pci_tree_node* tmp_node; public_adapter_info* adapter_p_node = (public_adapter_info*) p_node->node_info; curr_adapter = adapter_p_node; tmp_node = p_node->next; while (tmp_node) { if (tmp_node->type == 2) { public_function_info* function_p_node = (public_function_info*) tmp_node->node_info; if (!function_p_node->is_bridge) { curr_adapter->function = function_p_node; curr_adapter = NULL; break; } } tmp_node = tmp_node->next; } } break; } // end switch p_node = p_node->next; } // end while }// custom comparison function - assumes passed-in values are numeric static int dir_comp(const void* p1, const void* p2) { int num1, num2; char* c1 = (char*) p1; char* c2 = (char*) p2; while (*c1 != '/' && *c1 != '\0') c1++; if (*c1 == '/') c1++; while (*c2 != '/' && *c2 != '\0') c2++; if (*c2 == '/') c2++; num1 = atoi(c1); num2 = atoi(c2); if (num1 < num2) return -1; if (num1 > num2) return 1; return 0; // num1 == num2}// return the number of entries in the directory (with the noted exceptions)static int get_children(char* curr_dir, char* dir_name, int dir_name_length) { struct dirent* file; struct stat statbuf; int dir_size = 0; char* string; DIR *dp; char tmp_buf[MAXLEN]; sprintf(tmp_buf, "%s/%s", CPQPHPD_PROC_ROOT, curr_dir); if ((dp = opendir(tmp_buf)) == NULL) { fprintf(stderr, "Cannot open directory: %s \n", tmp_buf); return 0; } while ( (file = readdir(dp)) != NULL) { stat(file->d_name, &statbuf); if (S_ISDIR(statbuf.st_mode)) { if (strcmp(".", file->d_name) == 0 || strcmp("..", file->d_name) == 0 || strcmp(".info", file->d_name) == 0) continue; string = &(dir_name[dir_size*dir_name_length]); // get base address of directory name strcpy(string, file->d_name); dir_size++; } } closedir(dp); qsort(dir_name, dir_size, MAXLEN, dir_comp); return dir_size;};// visitation function that sets up the pci tree node pointers and invokes a call to// generate the viewable tree nodesstatic void walk_general_layer(GtkCTree* tree, char* curr_dir, GtkCTreeNode* parent, pci_tree_node* first_node, int info_visited){ // parse directory structure, call build_node to build and insert node data into tree char tmp_buff[255]; char directory_name[MAXSLOTS][MAXLEN]; pci_tree_node* curr_node = first_node; pci_tree_node* prev_node = NULL; int directory_size; strcpy(tmp_buff, curr_dir); do { if (!info_visited) { // node has not been visited before pci_tree_node* tmp_node = build_pci_tree_node(tmp_buff); if (tmp_node->type == 1) { // don't link bus node free(tmp_node); } else { prev_node = curr_node; curr_node = tmp_node; prev_node->next = curr_node; curr_node->node = prev_node->node; //Same Backpointer } } info_visited = 0; directory_size = get_children(tmp_buff, (char*) directory_name, MAXLEN); if (directory_size == 0) return; if (directory_size > 1) break; sprintf(tmp_buff, "%s/%s", tmp_buff, directory_name[0]); } while (1); walk_general_layer_recurse(tree, tmp_buff, parent);}// build the ctree and pci tree nodes and return to the layer above static void walk_general_layer_recurse(GtkCTree* tree, char* dir, GtkCTreeNode* parent) { int i; char dir_path[255]; char directory_name[MAXSLOTS][MAXLEN]; GtkCTreeNode* prev_ctree_node = NULL; GtkCTreeNode* curr_ctree_node = NULL; pci_tree_node* curr_pci_node; int directory_size = get_children(dir, (char*) directory_name, MAXLEN); for (i=0; i < directory_size; i++) { prev_ctree_node = curr_ctree_node; sprintf(dir_path, "%s/%s", dir, directory_name[i]); curr_pci_node = build_pci_tree_node(dir_path); curr_ctree_node = build_ctree_node(tree, parent, prev_ctree_node, curr_pci_node); curr_pci_node->node = curr_ctree_node; walk_general_layer(tree, dir_path, curr_ctree_node, curr_pci_node, 1); }}// skip the bus layer in the proc hierarchy and create the slot tree nodesvoid walk_top_layer(GtkCTree* tree, char* curr_dir){ DIR *dp, *dp2; int i; struct dirent *file; struct stat statbuf; char tmp_buff[MAXLEN]; memset(&root_nodes, 0, sizeof(root_nodes)); // initialize global root array memset(&root_paths, 0, sizeof(root_paths)); // initialize global root path array if ((dp = opendir(curr_dir)) == NULL) { fprintf(stderr, "Cannot open directory: %s \n", curr_dir); return; } root_paths_size = 0; while ( (file = readdir(dp)) != NULL) { stat(file->d_name, &statbuf); if (S_ISDIR(statbuf.st_mode) && (strcmp(".", file->d_name) != 0) && (strcmp("..", file->d_name) != 0) && (strcmp(".info", file->d_name) != 0)) { sprintf(tmp_buff,"%s/%s", curr_dir, file->d_name); dp2 = opendir(tmp_buff); if (dp2 != NULL) { struct dirent* file2; struct stat statbuf2; while ((file2 = readdir(dp2)) != NULL) { stat(file2->d_name, &statbuf2); if (S_ISDIR(statbuf.st_mode)) { if (strcmp(".", file2->d_name) == 0 || strcmp("..", file2->d_name) == 0 || strcmp(".info", file2->d_name) == 0) continue; sprintf(root_paths[root_paths_size],"%s/%s", file->d_name, file2->d_name); root_paths_size++; } } closedir(dp2); } } } qsort(root_paths, root_paths_size, MAXLEN, dir_comp); for (i=root_paths_size; i > 0; i--) { // 1-based to conform to slot-based build_from_slot(tree, i); } closedir(dp); // fix the back pointers for the adapter pci tree nodes for (i=0; i < root_paths_size; i++) { if (root_nodes[i] != 0) gtk_ctree_pre_recursive(tree, root_nodes[i], set_back_pointer, NULL); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -