/* Program Name : DIRECTKPD.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 FILES *** */ #include "global.h" #include "filer.h" #include "direct.h" #include "directkpd.h" #include strdef /* **** MACRO DEFINITIONS *** */ /** DIRTREE INACTIVE SCROLL REGION **/ #define DIRTREE_INACTIVE_ROWS (dirtree_display.view_rows/4) #define DIRTREE_INACTIVE_FRONT_ROW (1+DIRTREE_INACTIVE_ROWS) /* ** ** GLOBAL DECLARATIONS ** **/ extern struct node_tag *cwdnode, *root; extern struct display_tag dirtree_display; extern enum directions dirtree_search_direction; extern char dirtree_search_pattern[]; /* ** ** INTERNAL FUNCTION PROTOTYPING ** **/ static int dirtree_find_next$1(char *, struct node_tag **); static int dirtree_find_first$2(struct fil_dx_tag *, struct fil_dx_tag **); /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int dirtree_find_first() { char errmsg[256]; strcpy(errmsg, "Invalid directory specification or directory not found"); get_userinput_and_execute( dirtree_find_first$1, (dirtree_search_direction == advance? "Find Directory Forward" : "Find Directory Backward"), "Find What: ", "", errmsg, ""); return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int dirtree_find_first$1(pattern, dummy, errmsg) char *pattern; char *dummy; char *errmsg; { struct FAB fab; struct NAM nam; char expanded_pattern[NAM$C_MAXRSS]; char *cp; unsigned long int status; /* ** INITIALIZE FAB AND NAM DATA STRUCTURES **/ fab = cc$rms_fab; nam = cc$rms_nam; fab.fab$l_fna = pattern; fab.fab$b_fns = strlen(pattern); fab.fab$l_nam = &nam; fab.fab$l_dna = "*.*;*"; fab.fab$b_dns = strlen(fab.fab$l_dna); nam.nam$l_esa = &expanded_pattern; nam.nam$b_ess = NAM$C_MAXRSS; /* ** GET DIRECTORY SPEC USE 'OPEN' SYSTEM SERVICE. ** IGNORE THE ERROR STATUS (RMS$WLD). **/ if (sys$open(&fab, 0, 0) == RMS$_NORMAL) sys$close(&fab, 0, 0); expanded_pattern[ nam.nam$b_esl ] = EOS; if ((cp = strchr(expanded_pattern, ']')) != 0) *++cp = EOS; /** Preserve search string so that it can be used by FIND_NEXT. **/ strcpy(dirtree_search_pattern, expanded_pattern); return dirtree_find_next(); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int dirtree_find_next() { struct node_tag *n; int found; char *indx; char patternfilespec[MAXFILESPEC+1]; char name[MAXFILESPEC+1]; char short_path_name[MAXDIRSPEC+1]; $DESCRIPTOR(short_path_name_descrip, short_path_name); /* ** Convert from DEVNAME:[...DIRNAME] to DEVNAME:[.-]DIRNAME.DIR;1 **/ strcpy(patternfilespec, dirtree_search_pattern); if ((indx = strrchr(patternfilespec, '.')) == NULL) if ((indx = strchr(patternfilespec, '[')) == NULL) return -1; /* ** Get DIRNAME **/ indx++; strcpy(name, indx); if ((indx = strchr(name, ']')) == NULL) return -1; *indx = EOS; if (strcmp(name, "000000")) { /* ** NOT A SYSTEM MASTER DIRECTORY **/ indx = strchr(patternfilespec, ']'); *indx++ = '.'; *indx++ = '-'; *indx++ = ']'; *indx = EOS; } strcat(patternfilespec, name); strcat(patternfilespec, ".DIR;1"); found = dirtree_find_next$1(patternfilespec, &n); if (!found) return -1; else { 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_NORMAL, 0, 0)) cwdnode = n; } return 1; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ static int dirtree_find_next$1(pattern, nodep) char *pattern; struct node_tag **nodep; { static unsigned long context; $DESCRIPTOR(pattern_descrip, pattern); char candidate[MAXFILESPEC+1]; char candid_buf[MAXFILESPEC+1]; $DESCRIPTOR(candidate_descrip, candidate); unsigned long status; struct node_tag *n; char *p; *nodep = (struct node_tag *)NULL; LENGTH(pattern_descrip) = strlen(pattern); while ((status = lib$find_file ( &pattern_descrip, &candidate_descrip, &context, 0, 0, 0, 0)) != RMS$_NMF) { if (status == RMS$_NORMAL) { if ((p = strchr(candidate, ']')) != (char *)NULL) { /* ** Convert DEVNAME:[DIRNAME...]FILENAME.DIR;1 ** to DEVNAME:[DIRNAME...FILENAME] **/ *p = '.'; p = strrchr(candidate, '.'); *p = ']'; *++p = EOS; n = search_node(root, strchr(candidate, '[')+1); if (n == (struct node_tag *)NULL) { lib$find_file_end (&context); return 0; } if (dirtree_search_direction == backup) { if (n->row < cwdnode->row || (n->row == cwdnode->row && n->column < cwdnode->column)) { if (*nodep == (struct node_tag *)NULL) { *nodep = n; } else if ((*nodep)->row < n->row || ((*nodep)->row == n->row && (*nodep)->column < n->column)) { *nodep = n; } } } else if (n->row > cwdnode->row || (n->row == cwdnode->row && n->column > cwdnode->column)) { if (*nodep == (struct node_tag *)NULL) { *nodep = n; } else if ((*nodep)->row > n->row || ((*nodep)->row == n->row && (*nodep)->column > n->column)) { *nodep = n; } } } } } lib$find_file_end (&context); if (*nodep == (struct node_tag *)NULL) { return 0; } else { return 1; } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** to be specified ** **-- **/ int change_dirtree_viewport(dir_row, dir_col, dirtree_viewport_rowp, dirtree_viewport_colp) int dir_row, dir_col; int *dirtree_viewport_rowp, *dirtree_viewport_colp; { int filler_rows, number_of_scroll; int find_down_flag; struct node_tag *lastnode; int new_viewport_row, new_viewport_row1, lastnode_viewport_row; register int i; int dirtree_last_inactive_row = 1+((dirtree_display.view_rows-1)/LINESPACE)*LINESPACE; int dirtree_inactive_rear_row = dirtree_last_inactive_row-DIRTREE_INACTIVE_ROWS; /* ** Find the row number of the last node **/ find_down_flag = 0; find_down(root, (struct node_tag *)NULL, &lastnode, &find_down_flag); /* ** Compute new viewport row position **/ filler_rows = dirtree_display.view_rows-dirtree_last_inactive_row; lastnode_viewport_row = max(1, (int) lastnode->row+filler_rows-dirtree_display.view_rows+1); if (dir_row < *dirtree_viewport_rowp+DIRTREE_INACTIVE_FRONT_ROW-1) { /** TARGET ROW BEFORE INACTIVE FRONT ROW **/ new_viewport_row1 = max(1, (int) (dir_row-(DIRTREE_INACTIVE_FRONT_ROW-1))); new_viewport_row = min(new_viewport_row1, lastnode_viewport_row); number_of_scroll = *dirtree_viewport_rowp-new_viewport_row; if (number_of_scroll <= dirtree_display.view_rows/2) { /* ** The displacement between target row and current row ** is leq half of the screen, use scroll by line. **/ for (i = 1; i <= number_of_scroll; i++) check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_DOWN, &1)) *dirtree_viewport_rowp = new_viewport_row; } else { /* ** The displacement is larger than half the screen, ** use jump scroll instead. **/ new_viewport_row1 = max(1, (int) (dir_row-(dirtree_inactive_rear_row-1))); new_viewport_row = min(new_viewport_row1, lastnode_viewport_row); number_of_scroll = *dirtree_viewport_rowp-new_viewport_row; check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_DOWN, &number_of_scroll)) *dirtree_viewport_rowp = new_viewport_row; } } else if (dir_row > *dirtree_viewport_rowp+dirtree_inactive_rear_row-1) { /** Target row beyond inactive rear row **/ new_viewport_row1 = max(1, (int) (dir_row-(dirtree_inactive_rear_row-1))); new_viewport_row = min(new_viewport_row1, lastnode_viewport_row); number_of_scroll = new_viewport_row-*dirtree_viewport_rowp; if (abs(number_of_scroll) <= dirtree_display.view_rows/2) { /* ** The displacement between target row and current row ** is leq half of the screen, use scroll by line. **/ for (i = 1; i <= abs(number_of_scroll); i++) if (number_of_scroll > 0) check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_UP, &1)) else check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_DOWN, &1)) *dirtree_viewport_rowp = new_viewport_row; } else { /* ** The displacement is larger than half the screen, ** use jump scroll instead. **/ new_viewport_row1 = max(1, (int) (dir_row-(DIRTREE_INACTIVE_FRONT_ROW-1))); new_viewport_row = min(new_viewport_row1, lastnode_viewport_row); number_of_scroll = new_viewport_row-*dirtree_viewport_rowp; if (number_of_scroll > 0) check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_UP, &number_of_scroll)) else check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_DOWN, &number_of_scroll)) *dirtree_viewport_rowp = new_viewport_row; } } else if (lastnode->row <= *dirtree_viewport_rowp+dirtree_last_inactive_row-1) { /* ** Target node is in active area, and the ** last node in this directory tree is also in current screen. **/ new_viewport_row = lastnode_viewport_row; number_of_scroll = *dirtree_viewport_rowp-new_viewport_row; for (i = 1; i <= number_of_scroll && *dirtree_viewport_rowp > 1; i++, (*dirtree_viewport_rowp)--) check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_DOWN, &1)) } /* ** Compute new viewport column position **/ while (dir_col+MAXDIRSPEC > *dirtree_viewport_colp+dirtree_display.view_width-1) { check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_LEFT, &MAXDIRSPEC)) *dirtree_viewport_colp += MAXDIRSPEC; } while (dir_col < *dirtree_viewport_colp) { check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_RIGHT, &MAXDIRSPEC)) *dirtree_viewport_colp -= MAXDIRSPEC; } return DX__NORMAL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** FIND_DOWN(), FIND_RIGHT(), and FIND_LEFT() functions handle GOLD-key ** fast move. ** **-- **/ void find_down(curnode, parnode, q, flagp) struct node_tag *curnode; struct node_tag *parnode; struct node_tag **q; int *flagp; { if (curnode != (struct node_tag *)NULL) { if (curnode->left == parnode) { find_down(curnode->down, parnode, q, flagp); find_down(curnode->right, curnode, q, flagp); if (! *flagp) { *flagp = 1; *q = curnode; } } } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ struct node_tag * find_right(p) struct node_tag *p; { if (p->right == (struct node_tag *)NULL) return p; else return find_right(p->right); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ struct node_tag * find_left(p) struct node_tag *p; { if (p != (struct node_tag *)NULL) if (p->left->right == p) return find_left(p->left); else return p; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ struct node_tag *dirtree_page_down(n, lastnode) struct node_tag *n; struct node_tag *lastnode; { char short_path_name[MAXDIRSPEC+1]; /** Buffer to node name **/ $DESCRIPTOR(short_path_name_descrip, short_path_name); int max_scroll, number_of_scroll; int row, col, new_row, adjustment, i; int dirtree_last_inactive_row = 1+((dirtree_display.view_rows-1)/LINESPACE)*LINESPACE; sprintf(short_path_name, "%.8s", n->short_path_name); LENGTH(short_path_name_descrip) = strlen(short_path_name); check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &(n->row), &(n->column), 0, &SMG$M_NORMAL, 0, 0)) max_scroll = LINESPACE*((dirtree_display.view_rows-1)/LINESPACE); new_row = min((int)lastnode->row, (int)(cwdnode->row+max_scroll)); if (n->row == lastnode->row) /** CHANGE TO LAST NODE IF LAST ROW **/ n = lastnode; else /** FIND NEW NODE **/ n = search_node_page(root, new_row, n->column); /* ** SCROLL LESS THAN ONE FULL SCREEN IF NEW DIRECTORY IS NOT ** WITHIN THE INACTIVE AREA **/ adjustment = dirtree_display.view_rows-dirtree_last_inactive_row+1; if (n->row < dirtree_display.view_beg_y+dirtree_display.view_rows-adjustment+ DIRTREE_INACTIVE_FRONT_ROW-1) number_of_scroll = dirtree_display.view_rows-adjustment- (DIRTREE_INACTIVE_FRONT_ROW-1); else number_of_scroll = dirtree_display.view_rows-adjustment; /* ** SCROLL FILER DISPLAY. STOP AS SOON AS BOTTOM OF RECORD ** IS REACHED. **/ for (i = 1; i <= number_of_scroll && dirtree_display.view_beg_y+dirtree_display.view_rows-adjustment < lastnode->row; i++, dirtree_display.view_beg_y++) check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_UP, &1)) return n; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ struct node_tag *search_node_page (p, row, col) struct node_tag *p; int row; int col; { if (p == (struct node_tag *)NULL) return (struct node_tag *)NULL; else if (p->row < row) /** No node has been found with the given row **/ if (p->down == (struct node_tag *)NULL) return search_node_page(p->right, row, col); else if (p->down->row > row) return search_node_page(p->right, row, col); else return search_node_page(p->down, row, col); else if (p->column >= col || p->right == (struct node_tag *)NULL) return p; /** Target node found **/ else /** Search the nodes in the same row **/ return search_node_page(p->right, row, col); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ struct node_tag *dirtree_page_up (n) struct node_tag *n; { char short_path_name[MAXDIRSPEC+1]; /** Buffer to node name **/ $DESCRIPTOR(short_path_name_descrip, short_path_name); int max_scroll, number_of_scroll; int adjustment, new_row, i; int dirtree_last_inactive_row = 1+((dirtree_display.view_rows-1)/LINESPACE)*LINESPACE; int dirtree_inactive_rear_row = dirtree_last_inactive_row-DIRTREE_INACTIVE_ROWS; sprintf(short_path_name, "%.8s", n->short_path_name); LENGTH(short_path_name_descrip) = strlen(short_path_name); check_OK(smg$put_chars ( &dirtree_display.id, &short_path_name_descrip, &(n->row), &(n->column), 0, &SMG$M_NORMAL, 0, 0)) if (n->row == 1) /** ALREADY IN THE TOP ROW **/ n = root; else { /** SCROLL UP ONE SCREEN **/ max_scroll = LINESPACE*((dirtree_display.view_rows-1)/LINESPACE); new_row = max(1, (int)(n->row-max_scroll)); n = search_node_page(root, new_row, n->column); } /** CALCULATE NUMBER OF ROWS TO BE SCROLLED **/ adjustment = dirtree_display.view_rows-dirtree_last_inactive_row+1; if (n->row > dirtree_display.view_beg_y-(dirtree_display.view_rows-adjustment)+dirtree_inactive_rear_row-1) number_of_scroll = dirtree_display.view_rows-adjustment-(DIRTREE_INACTIVE_FRONT_ROW-1); else number_of_scroll = dirtree_display.view_rows-adjustment; /* ** SCROLL FILER DISPLAY. STOP AS SOON AS TOP OF RECORD ** IS REACHED. **/ for (i = 1; i <= number_of_scroll && dirtree_display.view_beg_y > 1; i++, dirtree_display.view_beg_y--) check_OK(smg$scroll_viewport ( &dirtree_display.id, &SMG$M_DOWN, &1)) return n; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ int direct_initial() { char initial_root[MAXFILESPEC+1]; char initial_usrnam[MAXFILESPEC+1]; char cwd_usrnam[MAXFILESPEC+1]; char prompt[MAXFILESPEC+1]; char errmsg[MAXFILESPEC+1]; char short_path_name[MAXDIRSPEC+1]; $DESCRIPTOR(short_path_name_descrip, short_path_name); char *cp; struct node_tag *n; char dirbuf[MAXFILESPEC+1]; /* ** Compare initial root directory name with current root ** directory name **/ find_root(DX_CURRENT_DIRECTORY.cur_dir, initial_root); /* ** Un-highlight current directory **/ 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_NORMAL, 0, 0 )) cwdnode = search_node(root, strchr(DX_CURRENT_DIRECTORY.cur_dir, '[')+1); return DX__NORMAL; }