sub find_dirs ! Written by Michael W. Wheeler (mww@tntech.bitnet) ! VAX Basic V3.1 ! Copyright (c) by Michael W. Wheeler, September 1987 ! This program is intended for Public Domain, and may not be sold or ! marketed in any form without the permision and written consent ! from the author Michael W. Wheeler. I retain all copyrights to ! this program, in either the original or modified forms, and no ! violation, deletion, or change of the copyright notice is ! allowed. Futhermore, I will have no liability or responsibilty ! to any user with respect to loss or damage caused directly or ! indirectly by this program. ! Lables ! dir_number: ! Constants %include "$ssdef" %from %library "sys$library:basic$starlet.tlb" %include "$rmsdef" %from %library "sys$library:basic$starlet.tlb" %include "$dvidef" %from %library "sys$library:basic$starlet.tlb" %include "$jpidef" %from %library "sys$library:basic$starlet.tlb" external long constant msg_notfound, msg_nocando, msg_nodef, & msg_unknown, msg_noscope, msg_noeventflg, & msg_illegal, msg_noaccess declare integer constant maxdirs = 2000 declare byte constant TRUE = -1, FALSE = 0 declare string constant dir_spec = "*.dir" ! Type (Record) record fixed_len string strng = 512 end record record itmlst word buf_len, itemcode long buf_loc, len_loc end record record iosblk long io_status, reserved end record ! Variables declare long cur_col, cur_row, sys_status, term_type, & return_status, context, dot_location, & dir_selection, scope declare word dir_count, len_dir, dot, colon, lbracket declare string dir_file, p1, full_name, dev, split_dir, & test_logical, print_string, search_str, & new_dir(maxdirs) declare fixed_len cur_dir declare itmlst itemlist(5%) declare iosblk iosb common (flags) byte dir, prompt, help, log_qual common (io_l) long term_table, col_len, num_cols, tt_cols, tt_rows common (io_w) word chan, max_dir, cursor_len, start_row, start_col common (rd_dirs) long col_compare ! Procedures (Sub) external sub read_dirs( string, string dim ( ) ), & fancy_selection( long, string dim ( ) ) ! Functions external long function lib$find_file, cli$get_value, & sys$setddir,lib$set_logical, & lib$getjpi, lib$sys_trnlog, sys$assign, & sys$getdviw, sys$dassgn, & smg$init_term_table_by_type external integer function find_last by desc ( string, string ) ! These are declared as variables but are used as constants. start_row = 5% start_col = 1% ! Fill item list for call to sys$getdviw( ). itemlist(1)::buf_len = 4% itemlist(1)::itemcode = dvi$_devtype itemlist(1)::buf_loc = loc(term_type) itemlist(1)::len_loc = 0% itemlist(2)::buf_len = 4% itemlist(2)::itemcode = dvi$_devbufsiz itemlist(2)::buf_loc = loc(tt_cols) itemlist(2)::len_loc = 0% itemlist(3)::buf_len = 4% itemlist(3)::itemcode = dvi$_tt_page itemlist(3)::buf_loc = loc(tt_rows) itemlist(3)::len_loc = 0% itemlist(4)::buf_len = 4% itemlist(4)::itemcode = dvi$_tt_scope itemlist(4)::buf_loc = loc(scope) itemlist(4)::len_loc = 0% itemlist(5)::buf_len = 0% itemlist(5)::itemcode = 0% itemlist(5)::buf_loc = 0% itemlist(5)::len_loc = 0% ! Assign a channel to the terminal. sys_status = sys$assign('sys$output',chan,,,) if (sys_status and 1%) = 0% then call lib$signal( sys_status by value ) end if ! Get device type, buffer size, page size, and whether it's a ! scope terminal or not. sys_status = sys$getdviw( , chan by value,, & itemlist(1%) by ref, & iosb by ref,,, ) if ((sys_status and 1%) = 0%) or ((iosb::io_status and 1%) = 0%) then call lib$signal( sys_status by value ) call lib$signal( iosb::io_status by value ) call sys$exit( 1% by value ) end if if tt_cols < 14% then tt_rows = tt_rows - 1% end if ! Allow extra line for wrapping. ! Call the help routine if /HELP was on the command line. if help then call help exit sub end if ! Was there a directory specification on the command line? if dir then return_status = cli$get_value("directory", p1) if return_status <> ss$_normal then call lib$signal( return_status by value ) end if ! Try to convert the specification to a number. call ots$cvt_ti_l( p1 by desc, dir_selection by ref ) ! Is it negative? if dir_selection < 0% then ! Negative number means look for a directory whose name is a number. p1 = num1$(abs%(dir_selection)) dir_selection = FALSE end if dir_number: ! If it converted to a number > 0 then if dir_selection will be true. if dir_selection then ! The specification was a number. call read_dirs( "", new_dir( ) ) if dir_selection > max_dir then dir_selection = FALSE goto dir_number end if call set_dir( new_dir(dir_selection) ) if prompt = TRUE then dot = find_last(".", new_dir(dir_selection)) + 1% call set_prompt( mid(new_dir(dir_selection), dot, instr(1%, new_dir(dir_selection), "]") - dot) ) end if else ! Must be a directory name specification. sys_status = lib$sys_trnlog( p1 by desc,, test_logical by desc,,, ) ! Try to translate if as if it were a logical name. if sys_status = ss$_normal then p1 = p1 + ":" else if (sys_status and 1%) = 0% then call lib$signal( sys_status by value ) end if end if colon = instr(0%, p1, ":") lbracket = instr(0%, p1, "[") dot = instr(0%, p1, ".") if (lbracket = 0%) and (colon = 0%) and (dot) then if dot <> 1% then p1 = "[." + p1 + "]" else p1 = "[" + p1 + "]" end if lbracket = instr(0%, p1, "[") end if if colon or lbracket then search_str = p1 + "*.*" sys_status = lib$find_file( search_str, dir_file, context ) ! if status is not successful then user doesn't have ! access to that directory. if (sys_status <> rms$_normal and sys_status <> rms$_fnf) then if sys_status <> rms$_dnf then call lib$signal( sys_status by value ) call lib$signal( msg_noaccess by value ) else call lib$stop( sys_status by value ) end if end if ! Split the specification into device/logical and directory specs. call split( p1, dev, split_dir, colon, lbracket ) if split_dir <> "" then call set_dir( p1 ) end if ! If there was a device specification then change the default device. if dev <> "" then return_status = lib$set_logical( "SYS$DISK" by desc, & dev by desc,,, ) if (return_status <> ss$_supersede) and (return_status <> ss$_normal) then call lib$signal( return_status by value ) end if end if if prompt then ! Set the DCL prompt based on the new directory. return_status = sys$setddir( 0% by value, & len_dir by ref, & cur_dir::strng by desc ) if return_status <> rms$_normal then call lib$signal( return_status by value ) end if dot = find_last(".", cur_dir::strng) if dot = 0% then dot = 1% end if right_braket = instr(0%, cur_dir::strng, "]") dir_file = mid(cur_dir::strng, dot+1%, right_braket-(dot+1%)) call set_prompt( dir_file ) end if exit sub end if context = 0 return_status = sys$setddir( 0% by value, & len_dir by ref, & cur_dir::strng by desc ) if return_status <> rms$_normal then call lib$signal( return_status by value ) end if full_name = "[...]" + p1 + ".dir" return_status = lib$find_file( full_name, dir_file, context ) ! If directory not found the search from the root down if not already ! at the root. if (return_status <> rms$_normal) and (instr(0%, cur_dir::strng, ".")) then dot_location = instr(0%, cur_dir::strng, ".") if dot_location then full_name = mid(cur_dir::strng, 0%, dot_location) + "..]" + p1 + ".dir" else full_name = mid(cur_dir::strng,0%,len_dir - 1%) + "...]" + p1 + ".dir" end if return_status = lib$find_file( full_name, dir_file, context ) end if if return_status = rms$_normal then ! Sucessful status - set default. right_braket = instr(0%, dir_file, "]") mid(dir_file, right_braket, 1%) = "." new_braket = instr(right_braket, dir_file, ";") - 4% mid(dir_file, new_braket, 1%) = "]" dir_file = mid(dir_file, 0%, new_braket) search_str = dir_file + "*.*" sys_status = lib$find_file( search_str, search_str, context ) ! if status is not successful then user doesn't have ! access to that directory. if (sys_status <> rms$_normal and sys_status <> rms$_fnf) then if sys_status <> rms$_dnf then call lib$signal( sys_status by value ) call lib$signal( msg_noaccess by value ) else call lib$stop( sys_status by value ) end if end if call set_dir( dir_file ) dir_file = mid(dir_file, right_braket+1%, new_braket-right_braket - 1%) if prompt then call set_prompt( dir_file ) end if else ! Bad specification. call lib$signal(msg_notfound by value) end if exit sub end if else call read_dirs( "", new_dir( ) ) if max_dir = 1% then ! If only one subdirectory in current directory and none was specified ! on the command line then set default to it. call set_dir(new_dir(1%)) if prompt then dot = find_last(".", new_dir(1%)) + 1% call set_prompt( mid(new_dir(1%), dot, instr(1%, new_dir(1%), "]") - dot) ) end if exit sub end if dir_count = 1% cur_col = 1% cur_row = 1% cursor_len = 0% if tt_rows < start_row then call lib$signal(msg_nocando by value, 1% by value, start_row by value) exit sub end if col_len = min(20%, tt_cols) num_cols = tt_cols / col_len col_compare = num_cols * col_len - col_len ! Get the definition for the type of terminal we are running on. sys_status = smg$init_term_table_by_type(term_type, term_table) if (Sys_status and 1%) = 0% then call lib$signal(msg_nodef by value) call lib$signal(msg_unknown by value) !call lib$signal(msg_hardcopy by value) !call hardcopy call lib$signal( sys_status by value ) else if scope = 0% then call lib$signal(msg_noscope by value) !call lib$signal(msg_hardcopy by value) !call hardcopy end if end if call fancy_selection( dir_selection, new_dir( ) ) if (dir_selection < 0%) or (dir_selection > max_dir) then call lib$signal( msg_illegal by value ) exit sub end if if dir_selection <> 0% then call set_dir(new_dir(dir_selection)) if prompt then dot = max(find_last(".", new_dir(dir_selection)) + 1%, & instr(0%, new_dir(dir_selection), "[") + 1%) call set_prompt( mid(new_dir(dir_selection), dot, instr(1%, new_dir(dir_selection), "]") - dot) ) end if exit sub end if ! Deassign the channel. sys_status = sys$dassgn (chan by value) if (sys_status and 1%) = 0% then call lib$signal( sys_status by value ) end if end if subend