Path: utzoo!attcan!uunet!samsung!uakari.primate.wisc.edu!sdd.hp.com!elroy.jpl.nasa.gov!ncar!gatech!prism!prism.gatech.EDU!gw18 From: gw18@prism.gatech.EDU (Greg Williams) Newsgroups: comp.windows.open-look Subject: XView scrolling list bug? Message-ID: <23080@hydra.gatech.EDU> Date: 28 Feb 91 20:34:31 GMT Sender: gw18@prism.gatech.EDU Organization: Georgia Institute of Technology Lines: 421 The following program produces an intermitant "Memory fault" crash. Its occuring sometime before the routine "dir_proc" is called. The crash is somewhere inside "xv_get". It takes a few minutes of playing and changing directories to get the initial crash, but after it crashes once, I can usually reproduce the crash, but not every time. I've run this code on a 4/65 and a 4/490, and get the same error. I'm running Open Windows as supplied by Sun. Can anyone tell me if I'm doing something wrong with the XView code? The crash occurs too often to ignore it. I appreciate any and all help I get. ----code begins here---- /* * This program creates two scrolling lists, one with directories and one * with files. It allows the user to search through directories for files * and then select a file to "open". */ #include #include #include #include #include #include #include #define DESELECT 0 #define SELECT 1 #define ENTRY_KEY 5877 #define NULL_STR "" Frame frame; Panel panel; Panel_item pi_dir, pi_file, ti_file, mi_dir, bi_open; DIR *dirp; struct dirent *entry; char *current; int num_files, num_dirs; int Open(); int Cancel(); void setup_list(); void dir_proc(); void file_proc(); int check_read(); main(argc, argv) int argc; char *argv[]; { char *tmpname; /* * Start in the HOME directory */ tmpname = getenv("HOME"); current = (char *)malloc(strlen(tmpname)+1); memset(current, '\0', strlen(tmpname)+1); strcat(current, tmpname); free(tmpname); xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL); frame = (Frame)xv_create(NULL, FRAME, FRAME_LABEL, "File Open", NULL); panel = (Panel)xv_create(frame, PANEL, NULL); mi_dir = (Panel_item)xv_create(panel, PANEL_MESSAGE, PANEL_LABEL_STRING, current, PANEL_LABEL_BOLD, TRUE, NULL); ti_file = (Panel_item)xv_create(panel, PANEL_TEXT, PANEL_LABEL_STRING, "File:", PANEL_VALUE_DISPLAY_LENGTH, 50, PANEL_VALUE_STORED_LENGTH, 256, PANEL_NEXT_ROW, -1, PANEL_VALUE, NULL_STR, NULL); pi_dir = (Panel_item)xv_create(panel, PANEL_LIST, PANEL_LABEL_STRING, "Directories:", PANEL_LIST_DISPLAY_ROWS, 10, PANEL_CHOOSE_ONE, TRUE, PANEL_CHOOSE_NONE, TRUE, PANEL_READ_ONLY, TRUE, PANEL_NOTIFY_PROC, dir_proc, PANEL_NEXT_ROW, -1, PANEL_LIST_WIDTH, 150, PANEL_LAYOUT, PANEL_VERTICAL, NULL); pi_file = (Panel_item)xv_create(panel, PANEL_LIST, PANEL_LABEL_STRING, "Files:", PANEL_LIST_DISPLAY_ROWS, 10, PANEL_CHOOSE_ONE, TRUE, PANEL_CHOOSE_NONE, TRUE, PANEL_READ_ONLY, TRUE, PANEL_NOTIFY_PROC, file_proc, PANEL_LIST_WIDTH, 150, PANEL_LAYOUT, PANEL_VERTICAL, NULL); bi_open = (Panel_item)xv_create(panel, PANEL_BUTTON, PANEL_LABEL_STRING, "Open", PANEL_NOTIFY_PROC, Open, XV_X, 370, XV_Y, 73, NULL); (void)xv_create(panel, PANEL_BUTTON, PANEL_LABEL_STRING, "Cancel", PANEL_NOTIFY_PROC, Cancel, XV_X, 367, XV_Y, 103, NULL); if (check_read(current)) setup_list(); window_fit(panel); window_fit(frame); xv_main_loop(frame); } /* * Re-read the directory entries for the scrolling lists */ void setup_list() { char *tmpname; int i; xv_set(ti_file, PANEL_VALUE, NULL_STR, NULL); xv_set(bi_open, XV_SHOW, FALSE, NULL); xv_set(mi_dir, PANEL_LABEL_STRING, current, NULL); /* * Hide the scroll lists while re-computing the lists. Saves on re-draw * time. */ xv_set(pi_dir, XV_SHOW, FALSE, NULL); xv_set(pi_file, XV_SHOW, FALSE, NULL); /* * First delete the old entries */ for (i = num_dirs - 1; i >= 0; i--) xv_set(pi_dir, PANEL_LIST_DELETE, i, NULL); for (i = num_files - 1; i >= 0; i--) xv_set(pi_file, PANEL_LIST_DELETE, i, NULL); num_files = 0; num_dirs = 0; /* * Now read the new entries */ dirp = opendir(current); while ((entry = readdir(dirp)) != NULL) { tmpname = (char *)malloc(strlen(current) + entry->d_namlen + 2); memset(tmpname, '\0', strlen(current) + entry->d_namlen + 2); strcat(tmpname, current); strcat(tmpname, "/"); strcat(tmpname, entry->d_name); if (dir_test(tmpname)) { /* * A directory */ if (strcmp(entry->d_name, ".")) { xv_set(pi_dir, PANEL_LIST_INSERT, num_dirs, PANEL_LIST_STRING, num_dirs, entry->d_name, NULL); num_dirs++; } } else { /* * A file */ if (strncmp(entry->d_name, ".", 1)) { xv_set(pi_file, PANEL_LIST_INSERT, num_files, PANEL_LIST_STRING, num_files, entry->d_name, NULL); num_files++; } } free(tmpname); } /* * Done, show the new scroll panels */ xv_set(pi_dir, XV_SHOW, TRUE, NULL); xv_set(pi_file, XV_SHOW, TRUE, NULL); closedir(dirp); } /* * Handle the selection of a directory entry in the scroll list */ void dir_proc(item, string, client_data, op, event) Panel_item item; char *string; caddr_t client_data; Panel_list_op op; Event *event; { char *oldcurrent; int i; /* * Make sure the user selected and didn't drag. Dragging may cause unwanted * changes */ if (op == SELECT && event_id(event) != LOC_DRAG && /* * Make sure we can read the directory before making any changes */ check_read(current, string)) { oldcurrent = (char *)malloc(strlen(current)+1); memset(oldcurrent, '\0', strlen(current)+1); strcat(oldcurrent, current); free(current); if (strcmp(string, "..")) { /* * Add the new directory to the "current" directory string */ current = (char *)malloc(strlen(oldcurrent) + strlen(string) + 2); memset(current, '\0', strlen(oldcurrent) + strlen(string) + 2); strcat(current, oldcurrent); if (strlen(oldcurrent) > 1) strcat(current, "/"); strcat(current, string); } else { /* * Go back one directory */ i = strlen(oldcurrent); while(oldcurrent[i] != '/') { oldcurrent[i] = '\0'; i--; } /* * Tried to go back from the root directory? */ if (i < 1) { oldcurrent[0] = '/'; oldcurrent[1] = '\0'; i = 1; } else oldcurrent[i] = '\0'; current = (char *)malloc(i); memset(current, '\0', i); strcat(current, oldcurrent); } free(oldcurrent); setup_list(); } } /* * Handle a selection on the file list */ void file_proc(item, string, client_data, op, event) Panel_item item; char *string; caddr_t client_data; Panel_list_op op; Event *event; { if (op == SELECT) { xv_set(ti_file, PANEL_VALUE, string, NULL); xv_set(bi_open, XV_SHOW, TRUE, NULL); } else if (op == DESELECT) { xv_set(ti_file, PANEL_VALUE, NULL_STR, NULL); xv_set(bi_open, XV_SHOW, FALSE, NULL); } } /* * Acknowledge an Open button press */ int Open(item, event) Panel_item item; Event *event; { if (strcmp(NULL_STR, (char *)xv_get(ti_file, PANEL_VALUE))) { printf("Open: %s\n", xv_get(ti_file, PANEL_VALUE)); xv_destroy_safe(frame); } } int Cancel(item, event) Panel_item item; Event *event; { xv_destroy_safe(frame); } /* * This routine tests to see if a file name is a directory entry */ dir_test(filename) char *filename; { struct stat statbuf; stat(filename, &statbuf); return(S_ISDIR(statbuf.st_mode)); } /* * Check to see if the directory is readable */ int check_read(oldpath, newdir) char *oldpath, *newdir; { char *both; DIR *test_open; both = (char *)malloc(strlen(oldpath) + strlen(newdir) + 2); memset(both, '\0', strlen(oldpath) + strlen(newdir) + 2); strcat(both, oldpath); strcat(both, "/"); strcat(both, newdir); if (!(test_open = opendir(both))) { free(both); return 0; } else { free(both); closedir(test_open); return 1; } } ----code ends here----