/* Program Name : DIRECT.C */ /* Original Author : C. K. Hung */ /* Date : 7-12-89 */ /* Program Description : */ /* : */ /* References */ /* Files open for Input : */ /* Files open for Output : */ /* Modules Referenced : */ /* Revision History follows */ #include "global.h" #include "direct.h" #include "directque.h" #include "directkpd.h" #include "dx.h" #include "filer.h" #include "inquire.h" #include /* ** GLOBAL DECLARATION ** */ struct node_tag *root, /** Root directory **/ *cwdnode; /** Current working directory **/ enum directions dirtree_search_direction; char dirtree_search_pattern[MAXFILESPEC+1]; /* **** VIRTUAL DISPLAY IDs *** */ struct display_tag dirtree_cmds_display; struct display_tag dirtree_display; /* **** INTERNAL FUNCTION PROTOTYPING *** */ static int traverse_tree$1(struct node_tag *, struct node_tag *, int, int, enum directions); static int direct_alarm_working$1(); /* ** FUNCTIONAL DESCRIPTION: * */ int filer_direct() { char initial_root[MAXFILESPEC+1]; /** Initial root directory **/ int n; unsigned long status_flags; int status; char errmsg[MAXFILESPEC+1]; int (*cstat)(); /* ** Output 'working...' message if total processing time ** is longer than 3 seconds. Needs to disable broadcast message ** first to avoid interference. **/ #ifndef DEBUG check_OK(smg$disable_broadcast_trapping ( &cntrl_info_block.pasteboard_id)) cstat = signal(SIGALRM, filter_alarm_working); alarm(1); #endif /* ** Start building the directory tree. ** Find the root directory. **/ find_root(DX_CURRENT_DIRECTORY.cur_dir, initial_root); /* ** Assign new value related to the directory tree. ** Do not free up the memory used by the tree. it might ** be used the cache queue. **/ if ((n = search_direct_cache(initial_root)) == -1) { /** This is a new directory tree **/ dirtree_search_direction = advance; strcpy(dirtree_search_pattern, "[]"); root = (struct node *)NULL; status = build_dirtree(&root, initial_root); if (status == DX__ERROR) { signal_err("Insufficient virtual memory", bell); free_dirtree(&root, (struct node_tag *)NULL); return DX__ERROR; } } else { /** This directory tree was saved in the cache queue **/ restore_from_direct_cache( n, &dirtree_search_direction, dirtree_search_pattern, &root); } traverse_tree(root, (struct node_tag *)NULL, 1, 1, dummy); /* ** Set the signal back to system default **/ #ifndef DEBUG alarm(0); signal(SIGALRM, cstat); check_OK(smg$erase_chars ( &cntrl_info_block.commands_display.id, &10, &2, &1)) check_OK(smg$set_broadcast_trapping ( &cntrl_info_block.pasteboard_id, broadcast_routine, 0)) #endif /* ** Create a directory commands display **/ dirtree_cmds_display.rows = cntrl_info_block.pasteboard_rows; dirtree_cmds_display.width = cntrl_info_block.pasteboard_width; dirtree_cmds_display.beg_y = DIRTREE_CMDS_PBD_ROW; dirtree_cmds_display.beg_x = DIRTREE_CMDS_PBD_COLUMN; check_OK(smg$create_virtual_display ( &cntrl_info_block.pasteboard_rows, &cntrl_info_block.pasteboard_width, &dirtree_cmds_display.id, &SMG$M_TRUNC_ICON, 0, 0)) check_OK(smg$paste_virtual_display ( &dirtree_cmds_display.id, &cntrl_info_block.pasteboard_id, &DIRTREE_CMDS_PBD_ROW, &DIRTREE_CMDS_PBD_COLUMN, 0)) /* ** Locate current directory in the tree. If not found, ** change initial directory to the root directory. **/ if ((cwdnode = search_node( root, strchr(DX_CURRENT_DIRECTORY.cur_dir, '[')+1)) == NULL) { cwdnode = root; } /** Change default directory **/ setddir(cwdnode->full_path_name, errmsg); dirtree_display.view_rows = cntrl_info_block.pasteboard_rows - DIRTREE_CMDS_RSV_LNS; dirtree_display.view_width = cntrl_info_block.pasteboard_width; /** Resize dirtree virtual display's size **/ dirtree_display.rows += dirtree_display.view_rows-1; dirtree_display.width += dirtree_display.view_width-MAXDIRSPEC; dirtree_display.beg_y = DIRTREE_PBD_ROW; dirtree_display.beg_x = DIRTREE_PBD_COLUMN; signal_err("Press RETURN to change directory, or keypad-0 to return", silence); put_dirtree_title(cwdnode); if (cntrl_info_block.user_pref.display_clock) write_time(dirtree_cmds_display.id); put_filer_pfs(DIRTREE_PFS, dirtree_cmds_display.id); check_OK(smg$create_virtual_display ( &dirtree_display.rows, &dirtree_display.width, &dirtree_display.id, &SMG$M_TRUNC_ICON, 0, 0)) paint_dirtree_display(root); dirtree_display.view_beg_y = dirtree_display.view_beg_x = 1; check_OK(smg$create_viewport ( &dirtree_display.id, &dirtree_display.view_beg_y, &dirtree_display.view_beg_x, &dirtree_display.view_rows, &dirtree_display.view_width)) /** Position viewport using current working directory **/ change_dirtree_viewport( cwdnode->row, cwdnode->column, &dirtree_display.view_beg_y, &dirtree_display.view_beg_x); check_OK(smg$paste_virtual_display ( &dirtree_display.id, &cntrl_info_block.pasteboard_id, &dirtree_display.beg_y, &dirtree_display.beg_x, 0)) dirtree_search_direction = advance; strcpy(dirtree_search_pattern, "[]"); direct_process_loop(); /** Clear error line if any **/ check_OK(smg$get_pasting_info ( &cntrl_info_block.status_display.id, &cntrl_info_block.pasteboard_id, &status_flags, 0, 0)) if (status_flags == SMG$M_DISPLAY_PASTED) { check_OK(smg$unpaste_virtual_display ( &cntrl_info_block.status_display.id, &cntrl_info_block.pasteboard_id)) } check_OK(smg$begin_pasteboard_update ( &cntrl_info_block.pasteboard_id)) check_OK(smg$erase_display ( &dirtree_cmds_display.id, 0, 0, 0, 0)) check_OK(smg$erase_display ( &dirtree_display.id, 0, 0, 0, 0)) check_OK(smg$end_pasteboard_update ( &cntrl_info_block.pasteboard_id)) check_OK(smg$delete_virtual_display ( &dirtree_cmds_display.id)) check_OK(smg$delete_virtual_display ( &dirtree_display.id)) /* ** Reset display ids. ** Will be checked by read_string_and_clear_errmsg(). **/ dirtree_cmds_display.id = dirtree_display.id = 0; /* ** Save to the directory cache queue. If it was previously ** saved in the queue, just replace the slot with ** root. Otherwise, find an empty slot to place root. **/ if ((n = search_direct_cache(initial_root)) == -1) { /* ** Current directory info not found in the ** directory cache. Find the LRU slot in the cache. **/ n = find_LRU_in_direct_cache(); } /* ** Save this directory information to the direct cache queue. **/ save_to_direct_cache( n, initial_root, dirtree_search_direction, dirtree_search_pattern, root); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int direct_process_loop() { char errmsg[256]; /** Error msg buffer **/ char *cp; unsigned long int status; char keyname[16]; $DESCRIPTOR (keyname_descrip, keyname); char short_path_name[MAXFILESPEC+1]; $DESCRIPTOR (short_path_name_descrip, short_path_name); unsigned long status_flags; /** SMG$READ_KEYSTROKE status **/ unsigned short keystroke; int find_down_flag; struct node_tag *lastnode, *leftnode; int timeout = cntrl_info_block.user_pref.update_in_second? 1 : 60; int (*cstat)(); /* ** Keep processing until exits by user. ** Exit is done by pressing kp0 or exit command. **/ do { /** Update changes made from last command **/ setddir(cwdnode->full_path_name, errmsg); change_dirtree_viewport( cwdnode->row, cwdnode->column, &dirtree_display.view_beg_y, &dirtree_display.view_beg_x); put_dirtree_title(cwdnode); sprintf(short_path_name, "%.8s", cwdnode->short_path_name); LENGTH(short_path_name_descrip) = strlen(short_path_name); check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_REVERSE, 0, 0)) /* ** Read next command. ** Clear error message line if any **/ do { status_flags = smg$read_keystroke ( &cntrl_info_block.keyboard_id, &keystroke, 0, &timeout, 0, 0, 0); if (cntrl_info_block.user_pref.display_clock) write_time(dirtree_cmds_display.id); } while (status_flags == SS$_TIMEOUT || keystroke == SMG$K_TRM_CANCELLED); check_OK(smg$get_pasting_info ( &cntrl_info_block.status_display.id, &cntrl_info_block.pasteboard_id, &status_flags, 0, 0)) if (status_flags == SMG$M_DISPLAY_PASTED) { check_OK(smg$unpaste_virtual_display ( &cntrl_info_block.status_display.id, &cntrl_info_block.pasteboard_id)) } /* ** Do job according to key pressed **/ switch (keystroke) { /** Exit without changing directory **/ case SMG$K_TRM_KP0: setddir(DX_CURRENT_DIRECTORY.cur_dir, errmsg); break; case SMG$K_TRM_KP1: /** Help command **/ direct_helpdir(); break; case SMG$K_TRM_KP2: /** Forward/backward switch **/ if (dirtree_search_direction == advance) { dirtree_search_direction = backup; } else { dirtree_search_direction = advance; } put_dirtree_title(cwdnode); break; case SMG$K_TRM_KP3: /** Find first command **/ dirtree_find_first(); break; case SMG$K_TRM_KP4: /** Find next command **/ if (dirtree_find_next() == DX__ERROR) signal_err("Directory not found", bell); break; case SMG$K_TRM_KP5: /** Goto top **/ check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = root; break; case SMG$K_TRM_KP6: /** Goto dirtree_display.rows **/ check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) find_down_flag = 0; find_down(root, (struct node_tag *)NULL, &cwdnode, &find_down_flag); break; case SMG$K_TRM_KP7: /** Goto initial **/ direct_initial(); break; case SMG$K_TRM_KP8: /** Page up/down **/ if (dirtree_search_direction == advance) { find_down_flag = 0; find_down(root, (struct node_tag *)NULL, &lastnode, &find_down_flag); if (cwdnode == lastnode) signal_err("Already at bottom of directory tree", bell); else cwdnode = dirtree_page_down(cwdnode, lastnode); } else if (cwdnode == root) { signal_err("Already at top of directory tree", bell); } else { cwdnode = dirtree_page_up(cwdnode); } break; case SMG$K_TRM_UP: /** Go up one directory **/ if (cwdnode == root) { signal_err("Already at top of directory tree", bell); } else { check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = (cwdnode->up != NULL)? cwdnode->up : cwdnode->left; } break; case SMG$K_TRM_DOWN: /** Go down one directory **/ if (cwdnode->down != NULL || cwdnode->right != NULL) { check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = (cwdnode->down != NULL)? cwdnode->down : cwdnode->right; } else { for (leftnode = cwdnode->left; leftnode != (struct node_tag *)NULL; leftnode = leftnode->left) if (leftnode->down != (struct node_tag *)NULL) if (leftnode->left == leftnode->down->left) break; if (leftnode == (struct node_tag *)NULL) signal_err("Already at bottom of directory tree", bell); else { check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = leftnode->down; } } break; case SMG$K_TRM_RIGHT: /** Go right one directory **/ if (cwdnode->right != NULL) { check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = cwdnode->right; } else { for (leftnode = cwdnode; leftnode != (struct node_tag *)NULL; leftnode = leftnode->left) if (leftnode->down != (struct node_tag *)NULL) if (leftnode->left == leftnode->down->left) break; if (leftnode == (struct node_tag *)NULL) { signal_err("Already at bottom of directory tree", bell); } else { check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = leftnode->down; } } break; case SMG$K_TRM_LEFT: /** Go left one directory **/ if (cwdnode == root) { signal_err("Already at top of directory tree", bell); } else { check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &cwdnode->row, &cwdnode->column, 0, &SMG$M_NORMAL, 0, 0)) cwdnode = (cwdnode->left != NULL)? cwdnode->left : cwdnode->up; } break; case SMG$K_TRM_CR: /** Change directory **/ /* ** Output 'working...' message if total processing time ** is longer than 1 second. Needs to disable broadcast message ** first because of interference. **/ check_OK(smg$disable_broadcast_trapping ( &cntrl_info_block.pasteboard_id)) cstat = signal(SIGALRM, direct_alarm_working); alarm(1); status = filer_filter$1( cwdnode->full_path_name, "Name", errmsg); /* ** Set the signal back to system default **/ alarm(0); signal(SIGALRM, cstat); check_OK(smg$erase_chars ( &dirtree_cmds_display.id, &10, &2, &1)) check_OK(smg$set_broadcast_trapping ( &cntrl_info_block.pasteboard_id, broadcast_routine, 0)) if (status == DX__ERROR) { signal_err(errmsg, bell); } else { return status; } break; case SMG$K_TRM_CTRLW: /** Refresh screen **/ check_OK(smg$repaint_screen ( &cntrl_info_block.pasteboard_id)) break; default: /** NO DEFINITION **/ memset (keyname, ' ', 15); smg$keycode_to_name ( &keystroke, &keyname_descrip); keyname[strcspn (keyname, " ")] = EOS; sprintf (errmsg, "Key '%s' currently has no definition", keyname); signal_err(errmsg, bell); } /** switch (keystroke) **/ } while ( keystroke != SMG$K_TRM_KP0); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int find_root(initdir, rootdir) char *initdir; char *rootdir; { int len; char *cp; len = strcspn(initdir, ".]"); strncpy(rootdir, initdir, len); rootdir[len] = ']'; rootdir[len+1] = EOS; cp = strchr(rootdir, '['); if (!strcmp(cp, "[0,0]") || !strcmp(cp, "[000,000]")) { /** Master system directory **/ *cp = EOS; strcat(rootdir, "[000000]"); } return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** CREATE_NODE() allocates virtual memory to a node. ** **-- **/ struct node_tag *create_node(filespec, row, col) char *filespec; int row; int col; { struct node_tag *newnode; char *start, *end; int i; int len; int allocate_size = sizeof (struct node_tag); unsigned long int status; /* ** ALLOCATE STOREAGE FOR A NEW NODE **/ check_OK(lib$get_vm ( &allocate_size, &newnode, 0)) /* ** Initialize the newly-created node **/ strcpy(newnode->full_path_name, filespec); if ((start = strrchr(filespec, '.')) == NULL) start = strchr(filespec, '['); start++; strcpy(newnode->short_path_name, start); end = strchr(newnode->short_path_name, ']'); *end = EOS; newnode->row = row; /** DIR COORDINATES **/ newnode->column = col; newnode->left = newnode->up = newnode->right = newnode->down = (struct node_tag *)NULL; /* ** Adjust the size of the dirtree display **/ dirtree_display.width = max(dirtree_display.width, col+MAXDIRSPEC-1); dirtree_display.rows = max(dirtree_display.rows, row); return newnode; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** BUILD_DIRTREE() expands "DEV:[USERNAME]*.DIR;1" wildcard and ** build a tree to be used for painting the DIRTREE virtual display. ** **-- **/ int build_dirtree(parentnode, pathname) struct node_tag **parentnode; char *pathname; { static _align (QUADWORD) int logicalQ[2]; static unsigned long context; struct logical_queue_entry_tag *E; unsigned long condcode; char *indx; int number_of_bytes; char filespec[MAXFILESPEC+1]; $DESCRIPTOR (filespec_descrip, filespec); char resultant_filespec[MAXFILESPEC+1]; $DESCRIPTOR (resultant_filespec_descrip, resultant_filespec); logicalQ[0] = logicalQ[1] = 0; trnlnm(pathname, logicalQ); while (_REMQHI (logicalQ, &E) != 3) { if (add_node(parentnode, E->equivalent_name, (struct node_tag *)NULL) == DX__ERROR) { return DX__ERROR; } /** Get wildcard file spec **/ strncpy(filespec, E->equivalent_name, strlen(E->equivalent_name)-1); filespec[ strlen(E->equivalent_name)-1 ] = EOS; number_of_bytes = strlen(E->equivalent_name)+1; check_OK(lib$free_vm ( &number_of_bytes, &E->equivalent_name, 0)) strcat(filespec, "...]*.DIR;1"); LENGTH(filespec_descrip) = strlen(filespec); /** Call system services to expand the wildcard */ while ((condcode = lib$find_file ( &filespec_descrip, &resultant_filespec_descrip, &context, 0, 0, 0, 0)) != RMS$_NMF) { if (condcode == RMS$_NORMAL && !strchr(resultant_filespec, '*') && strchr(resultant_filespec, ' ')) { /** Convert "DEV:[*.*...]*.DIR;1" into "DEV:[*.*...]" **/ for (indx = resultant_filespec; indx; indx++) if (*indx == ']') { *indx = '.'; break; } for (indx++; indx; indx++) if (*indx == '.') { *indx = ']'; break; } indx++; *indx = EOS; if (strstr (filespec, "[000000.")) { if (!strstr (resultant_filespec, "[000000.")) { char s[MAXFILESPEC+1]; indx = strchr(resultant_filespec, '[')+1; strcpy(s, indx); *indx = EOS; strcat(resultant_filespec, "000000."); strcat(resultant_filespec, s); } } if (add_node( parentnode, resultant_filespec, (struct node_tag *)NULL) == DX__ERROR) { lib$find_file_end(&context); return DX__ERROR; } } } lib$find_file_end(&context); } return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** add_node() inserts a node into the tree. ** **-- **/ struct node_tag *add_node(p, filespec, q) struct node_tag **p; char *filespec; struct node_tag *q; /* ** Parent node if moved right or ** sibling node if moved down **/ { struct node_tag *newnode; struct node_tag *upnode, *leftnode, *downnode, *rightnode; char *indx; int cmp; char *cp; int len; if (*p == (struct node_tag *)NULL) { newnode = create_node(filespec, 0, 0); /** Do double linking **/ if (q != (struct node *)NULL) { if (filespec[ strlen(q->full_path_name)-1 ] == '.') { /** New node is the oldest son **/ if ((newnode->up = find_prev_node(q)) != (struct node_tag *)NULL) newnode->up->down = newnode; newnode->left = q; } else { /** New node is a sibling **/ newnode->up = q; newnode->left = q->left; } } *p = newnode; return *p; } else if (filespec[ strlen((*p)->full_path_name)-1 ] == '.' && !strncmp( filespec, (*p)->full_path_name, strlen((*p)->full_path_name)-1)) { /** Search right **/ return add_node(&((*p)->right), filespec, *p); } else if (strncmp( filespec, (*p)->full_path_name, strlen((*p)->full_path_name)-1) > 0) { /** Search down **/ return add_node(&((*p)->down), filespec, *p); } else { if ((cp = strrchr((*p)->full_path_name, '.')) == NULL) { cp = strrchr((*p)->full_path_name, ']'); } len = cp-(*p)->full_path_name; if (strchr(filespec+len+1, '.') != NULL) { /* ** The parent directory did not exist prior to the ** creation of this directory **/ return (struct node_tag *)NULL; } else { newnode = create_node(filespec, 0, 0); /** Do double linking **/ if (q != (struct node *)NULL) { if (filespec[ strlen(q->full_path_name)-1 ] == '.') { /** New node is the oldest son **/ if ((newnode->up = (*p)->up) != (struct node_tag *)NULL) newnode->up->down = newnode; newnode->left = q; newnode->down = *p; (*p)->up = newnode; } else { /** New node is not the oldest son **/ newnode->up = q; newnode->left = (*p)->left; newnode->down = *p; (*p)->up = newnode; } } *p = newnode; return *p; } } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** FIND_PREV_NODE() finds previous node with different parent directory. ** **-- **/ struct node_tag *find_prev_node(q) struct node_tag *q; { struct node_tag *s; for (q = q->up; q != (struct node_tag *)NULL; q = q->up) { if (q->right != (struct node_tag *)NULL) { for (s = q->right; s->down != (struct node_tag *)NULL; s = s->down) if (s->down->left != q) return s; return s; } } return (struct node_tag *)NULL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** FIND_NEXT_NODE() finds next node with different parent directory. ** **-- **/ struct node_tag *find_next_node(q) struct node_tag *q; { struct node_tag *s; for (q = q->down; q != (struct node_tag *)NULL; q = q->down) { if (q->right != (struct node_tag *)NULL) { for (s = q->right; s->up != (struct node_tag *)NULL; s = s->up) if (s->up->left != q) return s; return s; } } return (struct node_tag *)NULL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** TRAVERSE_TREE() calculates the row and column value when ** visiting each node. The dimensions for DIRTREE are derived ** when the function finished. ** **-- **/ int traverse_tree(childnode, parentnode, row, col, direction) struct node_tag *childnode, *parentnode; int row, col; enum directions direction; { /** Reset DIRTREE virtual display's dimension **/ dirtree_display.rows = dirtree_display.width = 0; traverse_tree$1(childnode, parentnode, row, col, direction); /** Resize DIRTREE virtual display's size **/ dirtree_display.rows += dirtree_display.view_rows-1; dirtree_display.width += dirtree_display.view_width-MAXDIRSPEC; return DX__NORMAL; } static int traverse_tree$1(childnode, parentnode, row, col, direction) struct node_tag *childnode, *parentnode; int row, col; enum directions direction; { int lineno = 0; if (childnode == (struct node_tag *)NULL) { return (direction == right)? LINESPACE : 0; } else if (childnode->left == parentnode) { if (dirtree_display.width < col+MAXDIRSPEC-1) dirtree_display.width = col+MAXDIRSPEC-1; if (dirtree_display.rows < row) dirtree_display.rows = row; childnode->row = row; childnode->column = col; lineno += traverse_tree$1(childnode->right, childnode, row, col+DISTANCE_COUNT, right); lineno += traverse_tree$1(childnode->down, parentnode, row+lineno, col, down); } return lineno; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** SEARCH_NODE() searchs a node starting from the root directory. ** Return error if not found. ** **-- **/ struct node_tag *search_node(p, filespec) struct node_tag *p; char *filespec; { if (p == (struct node_tag *)NULL) { return (struct node_tag *)NULL; } else if (!strncmp(p->short_path_name, filespec, strlen(p->short_path_name)) && !strncmp(p->short_path_name, filespec, strcspn(filespec, ".]"))) /** A MATCHED DIRECTORY IS FOUND **/ { if (*(filespec+strlen(p->short_path_name)) == ']') return p; else return search_node(p->right, strchr(filespec, '.')+1); } else if (p->down != (struct node_tag *)NULL) { if (p->down->left == p->left) return search_node(p->down, filespec); } return (struct node_tag *)NULL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** PAINT_DIRTREE_DISPLAY() takes the tree head as input and ** writes the directory tree structure to the display. ** **-- **/ void paint_dirtree_display(p) struct node_tag *p; { char short_path_name[MAXDIRSPEC+1]; $DESCRIPTOR(short_path_name_descrip, short_path_name); unsigned int start_row, end_row, start_column, end_column; unsigned long char_up = SMG$M_LEFT + SMG$M_RIGHT + SMG$M_DOWN; unsigned long char_left = SMG$M_UP + SMG$M_DOWN + SMG$M_RIGHT; unsigned long left_corner = SMG$M_UP + SMG$M_RIGHT; unsigned long draw_char; if (p != (struct node_tag *)NULL) { sprintf(short_path_name, "%.8s", p->short_path_name); LENGTH(short_path_name_descrip) = strlen(short_path_name); check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &(p->row), &(p->column), 0, 0, 0, 0)) if (p->left != (struct node_tag *)NULL) { if (p->up == NULL) { start_column = p->left->column+min( strlen(p->left->short_path_name), MAXDIRSPEC); end_column = p->column-1; check_OK(smg$draw_line ( &dirtree_display.id, &(p->row), &start_column, &(p->row), &end_column, 0, 0)) } else if (p->left != p->up->left) { start_column = p->left->column+min( strlen(p->left->short_path_name), MAXDIRSPEC); end_column = p->column-1; check_OK(smg$draw_line ( &dirtree_display.id, &(p->row), &start_column, &(p->row), &end_column, 0, 0)) } else { if (p->up->up == (struct node_tag *)NULL) draw_char = char_up; else if (p->up->up->left != p->up->left) draw_char = char_up; else draw_char = char_left; start_column = p->up->column-LINE_NODE_DISTANCE; check_OK(smg$draw_char ( &dirtree_display.id, &draw_char, &(p->up->row), &start_column, 0, 0)) start_row = p->up->row+1; end_row = p->row; start_column = p->column-LINE_NODE_DISTANCE; check_OK(smg$draw_line ( &dirtree_display.id, &start_row, &start_column, &end_row, &start_column, 0, 0)) check_OK(smg$draw_char ( &dirtree_display.id, &left_corner, &(p->row), &start_column, 0, 0)) start_column = p->column-LINE_NODE_DISTANCE; end_column = p->column-1; check_OK(smg$draw_line ( &dirtree_display.id, &(p->row), &start_column, &(p->row), &end_column, 0, 0)) } } paint_dirtree_display(p->right); if (p->down != (struct node_tag *)NULL) if (p->left == p->down->left) paint_dirtree_display(p->down); } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** FREE_DIRTREE() makes the virtual memory previously allocated to ** DIRTREE available again. ** **-- **/ int free_dirtree(p, q) struct node_tag **p; struct node_tag *q; { int node_entry_size = sizeof (struct node_tag); if (*p != (struct node_tag *)NULL) { if ((*p)->left == q) { free_dirtree(&((*p)->down), q); free_dirtree(&((*p)->down), *p); check_OK(lib$free_vm ( &node_entry_size, p, 0)) *p = (struct node_tag *)NULL; } } return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int put_dirtree_title(n) struct node_tag *n; { char dir[10]; int rows_in_page, current_page; char str[81]; $DESCRIPTOR(str_descrip, str); char cwd_line[81]; $DESCRIPTOR(cwd_line_descrip, cwd_line); char page_str[81]; $DESCRIPTOR(page_str_descrip, page_str); struct fil_dx_tag *p; int line_row; int len; if (dirtree_search_direction == advance) { strcpy(dir, "Forward"); } else { strcpy(dir, "Backward"); } if (strlen(n->full_path_name) > 67) { sprintf(cwd_line, " %-66.66s~ | %-8.8s ", n->full_path_name, dir); } else { sprintf(cwd_line, " %-67.67s | %-8.8s ", n->full_path_name, dir); } LENGTH(cwd_line_descrip) = strlen(cwd_line); check_OK(smg$put_chars ( &dirtree_cmds_display.id, &cwd_line_descrip, &DIRTREE_DIRECT_ROW, &1, &SMG$M_ERASE_LINE, &SMG$M_REVERSE, 0, 0)) current_page = 1 + (n->row-1)/dirtree_display.view_rows; sprintf(page_str, "%d", current_page); LENGTH(page_str_descrip) = strlen(page_str); len = strlen(page_str)+2; line_row = cntrl_info_block.pasteboard_rows-1; check_OK(smg$draw_line ( &dirtree_cmds_display.id, &line_row, &1, &line_row, &1, 0, 0)) check_OK(smg$put_chars ( &dirtree_cmds_display.id, &page_str_descrip, &line_row, &2, 0, &SMG$M_BOLD, 0, 0)) check_OK(smg$draw_line ( &dirtree_cmds_display.id, &line_row, &len, &line_row, &dirtree_cmds_display.width, 0, 0)) return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** DIRECT_HELPDIR() calls HELPDIR() to output help message ** by using VMS HELP utilities. ** **-- **/ int direct_helpdir() { filer_help("DX OPTION_MENU MOVING_AROUND_DIRTREE"); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int direct_alarm_working() { static int remain_alarm = 2; if (cntrl_info_block.user_pref.display_clock && cntrl_info_block.user_pref.update_in_second) { write_time(dirtree_cmds_display.id); } remain_alarm--; if (remain_alarm > 0) { signal(SIGALRM, direct_alarm_working); } else { remain_alarm = 2; signal(SIGALRM, direct_alarm_working$1); } alarm(1); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ static int direct_alarm_working$1() { static int switch_on = 0; static int remain_timeout = 60; if (!switch_on) { switch_on++; check_OK(smg$put_chars ( &dirtree_cmds_display.id, $DESCR ("Working..."), &2, &1, 0, 0, 0, 0)) } else { switch_on = 0; check_OK(smg$erase_chars ( &dirtree_cmds_display.id, &10, &2, &1)) } if (cntrl_info_block.user_pref.display_clock) { if (cntrl_info_block.user_pref.update_in_second) { write_time(dirtree_cmds_display.id); } else { remain_timeout--; if (remain_timeout == 0) { write_time(dirtree_cmds_display.id); remain_timeout = 60; } } } signal(SIGALRM, direct_alarm_working$1); alarm(1); return DX__NORMAL; }