1%_debug_info = 1; 2% 3% Info reader for JED 4% 5 6variable Info_This_Filename = Null_String; 7variable Info_This_Filedir = Null_String; 8 9#ifndef VMS 10% returns compression extension if file is compressed or "" if not 11define info_is_compressed (file) 12{ 13 variable exts, ext, n; 14 exts = ".Z,.z,.gz,.bz2"; 15 n = 0; 16 forever 17 { 18 ext = extract_element(exts, n, ','); 19 if (ext == NULL) return ""; 20 21 if (1 == file_status(file + ext)) break; 22 n++; 23 } 24 ext; 25} 26#endif 27 28 29define info_make_file_name (file) 30{ 31 variable n, dir, dirfile, df, df_low; 32 variable cext = ""; % compressed extension 33 34 n = 0; 35 forever 36 { 37 % 38 % Try to find requested file in remembered directory. 39 % 40 dirfile = expand_filename(dircat(Info_This_Filedir, file)); 41 if (1 == file_status(dirfile)) break; 42 43 dir = extract_element(Info_Directory, n, ','); 44 if (dir == NULL) dir = ""; 45 df = expand_filename(dircat(dir,file)); 46 47 % try with first with info extension 48#ifdef VMS 49 dirfile = df + "info"; % VMS adds a '.' upon expansion 50#else 51 dirfile = df + ".info"; 52#endif 53 54 55 if (1 == file_status(dirfile)) break; 56#ifndef VMS 57 cext = info_is_compressed(dirfile); 58 if (strlen(cext)) break; 59#endif 60 df_low = expand_filename(dircat(dir,strlow(file))); 61 62#ifdef VMS 63 dirfile = df_low + "info"; % VMS adds a '.' upon expansion 64#else 65 dirfile = df_low + ".info"; 66#endif 67 68 if (1 == file_status(dirfile)) break; 69#ifndef VMS 70 cext = info_is_compressed(dirfile); 71 if (strlen(cext)) break; 72#endif 73 74 % try next with inf extension, since .info causes problems on FAT 75 % In addition, Unix and VMS distributions may have been derived from 76 % PC 8+3 distributions. 77 % 78 % Also Windows 95 supports long filenames. Since that OS is also 79 % considered to be MSDOS, we need to try this for MSDOS as well 80 % even though it has no effect under a true MSDOS system. 81 dirfile = df_low + ".inf"; 82 83 if (1 == file_status(dirfile)) break; 84#ifndef VMS 85 cext = info_is_compressed(dirfile); 86 if (strlen(cext)) break; 87#endif 88 89% repeat without extension 90 91 dirfile = df; 92 93 if (1 == file_status(dirfile)) break; 94#ifndef VMS 95 cext = info_is_compressed(dirfile); 96 if (strlen(cext)) break; 97#endif 98 dirfile = df_low; 99 if (1 == file_status(dirfile)) break; 100#ifdef UNIX 101 cext = info_is_compressed(dirfile); 102 if (strlen(cext)) break; 103#endif 104 105 !if (strlen(dir)) error ("Info file not found: " + file); 106 ++n; 107 } 108 109 (Info_This_Filedir, ) = parse_filename(dirfile); 110 111 return (dirfile, cext); 112} 113 114private define make_unzip_cmd (ext) 115{ 116 variable unzip_cmd = "uncompress -c"; 117 switch (ext) 118 { 119 case ".gz": 120 unzip_cmd = "gzip -dc"; 121 } 122 { 123 case ".bz2": 124 unzip_cmd = "bzip2 -dc"; 125 } 126 return unzip_cmd; 127} 128 129 130define info_find_file (file) 131{ 132 variable dirfile, flags, buf, dir; 133 variable ext; 134 135 (dirfile, ext) = info_make_file_name(file); 136 137 setbuf("*Info*"); 138 set_readonly(0); 139 widen(); erase_buffer(); 140 141#ifndef VMS 142 if (strlen(ext)) 143 () = run_shell_cmd (sprintf("%s %s%s", make_unzip_cmd (ext), dirfile, ext)); 144 else 145#endif 146 () = insert_file(dirfile); 147 148 bob(); 149 Info_This_Filename = dirfile; 150 set_readonly(1); 151 set_buffer_modified_flag(0); 152 set_mode("Info", 1); 153 use_keymap("Infomap"); 154 set_status_line(" Jed Info: %f (%m%n) Press '?' for help. (%p)", 0); 155 156 % The following 2 lines will cause problems when the buffer attached to 157 % the specified file is erased from a re-only directory. 158 %( , dir, buf, flags) = getbuf_info(); 159 %setbuf_info(extract_filename(Info_This_Filename), dir, buf, flags); 160} 161 162 163define info_find_node_split_file(); % extern 164 165variable Info_Split_File_Buffer; Info_Split_File_Buffer = Null_String; 166variable Info_Split_Filename; Info_Split_Filename = Null_String; 167 168define info_search_marker(dir) 169{ 170 variable mark, pnt, search_fun; 171 mark = "\x1F"; 172 if (dir > 0) search_fun = &fsearch; else search_fun = &bsearch; 173 push_mark(); 174 forever 175 { 176 if (not(@search_fun(mark))) 177 { 178 pop_mark_1 (); 179 return(0); 180 } 181 if (bolp()) break; 182 pnt = _get_point (); 183 bol(); skip_chars("\x01-\x1E "); 184 go_right_1 (); 185 pnt = _get_point () - pnt; 186 if ((pnt == 1) and (eolp() or looking_at_char('\xC'))) break; 187 if (dir > 0) eol(); else bol(); 188 } 189 pop_mark_0 (); 190 return (1); 191} 192 193define info_find_node_this_file (the_node) 194{ 195 variable node, len, fnd; 196 CASE_SEARCH = 0; 197 node = "Node: " + the_node; 198 len = strlen(node); 199 widen(); bob(); 200 forever 201 { 202 % some of this could/should be replaced by a regular expression: 203 % !if (re_fsearch("^[\t ]*\x1F")) .... 204 205 !if (info_search_marker(1)) 206 { 207 % dont give up, maybe this is a split file 208 !if (strlen(Info_Split_File_Buffer)) 209 error("Marker not found. " + node); 210 setbuf(Info_Split_File_Buffer); 211 info_find_node_split_file(the_node); 212 return; 213 } 214 go_down_1 (); % bol(); --- already implicit 215 if (ffind(node)) 216 { 217 % is this really it? --- 218 go_right(len); 219 if (eolp() or looking_at_char(',') or looking_at_char('\t')) break; 220 } 221 222 eol (); 223 } 224 225 push_mark(); 226 if (info_search_marker(1)) go_up_1(); else eob(); 227 narrow(); 228 bob(); 229} 230 231 232define info_find_node_split_file (node) 233{ 234 variable tag, tagpos, pos, pos_len, tag_len, buf, file; 235 variable re; 236 buf = " *Info*"; 237 238 !if (bufferp(buf), setbuf(buf)) 239 { 240 insbuf("*Info*"); 241 } 242 243 widen(); 244 245 % make this re safe 246 tag = str_quote_string (node, "\\^$[]*.+?", '\\'); 247 248 tag = "Node: " + tag; 249 eob(); 250 251 252 %!if (bol_bsearch(tag)) error("tag not found."); 253 %go_right(strlen(tag)); 254 %skip_chars(" \t\x7F"); 255 256 re = tag + "[\t \x7F]\\d+[ \t]*$"; 257 258 !if (re_bsearch(re)) verror ("tag %s not found.", tag); 259 eol (); 260 bskip_chars(" \t"); 261 push_mark(); bskip_chars ("0-9"); 262 tagpos = bufsubstr(); % see comment about DOS below 263 tag_len = strlen(tagpos); 264 265 bob (); 266 bol_fsearch("Indirect:"); pop(); 267 push_mark(); 268 !if (info_search_marker(1)) eob(); 269 narrow(); 270 bob(); 271 forever 272 { 273 !if (down_1 ()) break; 274 % bol(); --- implicit in down 275 !if (ffind(": ")) break; 276 go_right(2); 277 278 % This will not work on DOS with 16 bit ints. Do strcmp instead. 279 push_mark_eol(); pos = bufsubstr(); 280 pos_len = strlen(pos); 281 if (tag_len > pos_len) continue; 282 if (tag_len < pos_len) break; 283 % now == 284 if (strcmp(tagpos, pos) < 0) break; 285 } 286 287 Info_Split_File_Buffer = Null_String; 288 go_up_1 (); bol(); 289 push_mark(); 290 () = ffind(": "); 291 widen(); 292 file = bufsubstr(); 293 294 info_find_file(file); 295 info_find_node_this_file(node); 296 Info_Split_File_Buffer = buf; 297} 298 299 300 301define info_narrow() 302{ 303 if (whatbuf () != "*Info*") return; 304 push_spot(); push_spot(); 305 () = info_search_marker(-1); 306 go_down_1 (); push_mark(); 307 pop_spot(); 308 if (info_search_marker(1)) go_up_1 (); else eob(); 309 narrow(); 310 pop_spot(); 311} 312 313 314 % stack for last position 315 316!if (is_defined ("Info_Position_Type")) 317{ 318 typedef struct 319 { 320 filename, 321 split_filename, 322 line_number 323 } 324 Info_Position_Type; 325} 326 327 328variable Info_Position_Stack = Info_Position_Type [16]; 329variable Info_Stack_Depth = 0; 330 331define info_push_position(file, split, line) 332{ 333 variable i; 334 variable pos; 335 336 if (Info_Stack_Depth == 16) 337 { 338 --Info_Stack_Depth; 339 for (i = 1; i < 16; i++) 340 Info_Position_Stack [i - 1] = @Info_Position_Stack [i]; 341 } 342 343 pos = Info_Position_Stack [Info_Stack_Depth]; 344 345 pos.filename = file; 346 pos.split_filename = split; 347 pos.line_number = line; 348 349 ++Info_Stack_Depth; 350} 351 352 353define info_record_position () 354{ 355 variable i, file; 356 357 if (whatbuf() != "*Info*") return; 358 widen(); 359 file = Null_String; 360 361 if (strlen (Info_Split_File_Buffer)) file = Info_Split_Filename; 362 info_push_position(Info_This_Filename, file, what_line()); 363 info_narrow(); 364} 365 366 367 368 369define info_find_node(node) 370{ 371 variable the_node, file, n, len; 372 n = 0; 373 374 % Replace \n and \t characters in name by spaces 375 node = strcompress (node, " \t\n"); 376 377 info_record_position(); 378 ERROR_BLOCK 379 { 380 if (bufferp ("*Info*")) 381 info_reader (); 382 } 383 384 len = strlen(node); 385 % if it looks like (file)node, extract file, node 386 387 if (is_substr(node, "(") == 1) n = is_substr(node, ")"); 388 389 if (n) 390 { 391 variable save_node = "|" + node + "|"; 392 the_node = node; 393 node = substr(the_node, n + 1, strlen(node)); 394 the_node = strsub(the_node, n, 0); % truncate string 395 file = substr(the_node, 2, n-2); 396 if (bufferp(Info_Split_File_Buffer)) delbuf(Info_Split_File_Buffer); 397 Info_Split_File_Buffer = Null_String; 398 info_find_file(file); 399 } 400 401 node = strtrim (node); 402 !if (strlen(node)) node = "Top"; 403 widen(); 404 push_spot_bob (); 405 !if (info_search_marker(1)) error("Marker not found."); 406 go_down_1 (); 407 408 if (looking_at("Indirect:"), pop_spot()) 409 { 410 Info_Split_Filename = Info_This_Filename; 411 info_find_node_split_file(node); 412 } 413 else info_find_node_this_file(node); 414} 415 416 417% If buffer has a menu, point is put on line after menu marker if argument 418% is non-zero, otherwise leave point as is. 419% signals error if no menu. 420define info_find_menu(save) 421{ 422 variable menu_re = "^\\c\\* Menu:"; 423 push_spot(); 424 425 bob (); 426 427 forever 428 { 429 !if (re_fsearch(menu_re)) 430 { 431 pop_spot(); 432 error ("Node has no menu."); 433 } 434 435 go_right (7); 436 !if (looking_at_char (':')) 437 break; 438 } 439 440 !if (save) 441 { 442 pop_spot(); 443 return; 444 } 445 446 eol(); go_right_1 (); 447 push_mark(); pop_spot(); pop_mark_1 (); 448} 449 450 451 452% Move move the cursor to the start of the next nearest menu item or 453% note reference in this node if possible. 454% 455define info_next_xref () 456{ 457 push_mark (); go_right_1 (); 458 if (re_fsearch("\\*.*:")) exchange_point_and_mark (); 459 pop_mark_1 (); 460} 461% 462% Move move the cursor to the start of the previous nearest menu item or 463% note reference in this node if possible. 464% 465define info_prev_xref () 466{ 467 push_mark (); go_left_1 (); 468 if (re_bsearch("[*].*:")) exchange_point_and_mark (); 469 pop_mark_1 (); 470} 471 472 473% menu references 474 475define info_follow_current_xref () 476{ 477 variable node; 478 479 push_spot(); 480 481 !if (fsearch_char (':')) 482 { 483 pop_spot(); error ("Corrupt File?"); 484 } 485 486 if (looking_at("::")) 487 { 488 push_mark(); 489 pop_spot(); 490 node = bufsubstr(); 491 } 492 else 493 { 494 go_right_1 (); 495 skip_white(); 496 if (eolp()) 497 { 498 go_right_1 (); 499 skip_white(); 500 } 501 push_mark(); 502 if (looking_at_char('(')) () = ffind_char (')'); 503 % comma, tab, '.', or newline terminates 504 skip_chars ("^,.\t\n"); 505 %skip_chars("\d032-\d043\d045\d047-\d255"); 506 507 bskip_chars(" "); 508 node = bufsubstr(()); 509 pop_spot(); 510 } 511 info_find_node(node); 512} 513 514define info_menu () 515{ 516 variable node, colons, colon; 517 node = Null_String; 518 colon = ":"; colons = "::"; 519 520 if ((LAST_CHAR == '\r') and re_looking_at ("\\C*Note[ \t\n]")) 521 %and not(bolp ())) 522 { 523 go_right (5); skip_chars (" \t\n"); 524 info_follow_current_xref (); 525 return; 526 } 527 528 info_find_menu (0); 529 530 bol (); 531 532 if (looking_at("* ") 533 and (ffind(colon))) 534 { 535 push_mark(); 536 bol(); go_right(2); 537 node = bufsubstr() + colon; 538 bol (); 539 } 540 541 !if (strlen (node) and (LAST_CHAR == '\r')) 542 { 543 node = read_mini("Menu item:", node, Null_String); 544 info_find_menu (1); 545 } 546 547 !if (bol_fsearch("* " + node)) error ("Menu Item not found."); 548 !if (ffind(colon)) error ("Corrupt File?"); 549 550 if (looking_at(colons)) 551 { 552 push_mark(); 553 bol(); go_right(2); 554 } 555 else 556 { 557 go_right_1 (); 558 skip_white(); 559 push_mark(); 560 if (looking_at_char('(')) 561 { 562 () = ffind_char (')'); 563 } 564 % comma, tab, '.', or newline terminates 565 skip_chars ("^,.\t\n"); 566 %skip_chars("\d032-\d043\d045\d047-\d255"); 567 568 bskip_chars(" "); 569 } 570 info_find_node(bufsubstr(())); 571} 572 573define info_find_dir() 574{ 575 info_find_node ("(DIR)top"); 576} 577 578 579 580define info_up () 581{ 582 bob(); 583 !if (ffind("Up: ")) 584 { 585 info_find_dir (); 586 return; 587 } 588 589 go_right(4); push_mark(); 590 % comma, tab, or newline terminates 591 skip_chars ("^,.\t\n"); 592 %skip_chars("\d032-\d043\d045-\d255"); 593 bskip_chars(" "); 594 info_find_node(bufsubstr(())); 595} 596 597define info_prev() 598{ 599 variable n; n = 10; 600 bob(); 601 !if (ffind("Previous: ")) 602 { 603 !if (ffind("Prev: ")) error ("Node has no PREVIOUS"); 604 n = 6; 605 } 606 607 go_right(n); push_mark(); 608 skip_chars ("^,.\t\n"); 609 %skip_chars("\d032-\d043\d045-\d255"); 610 bskip_chars(" "); 611 info_find_node(bufsubstr(())); 612} 613 614 615define info_goto_last_position () 616{ 617 variable split_file, file, n; 618 variable pos; 619 620 if (Info_Stack_Depth == 0) return; 621 622 --Info_Stack_Depth; 623 624 pos = Info_Position_Stack [Info_Stack_Depth]; 625 626 split_file = pos.split_filename; 627 file = pos.filename; 628 n = pos.line_number; 629 630 if ((file == Info_This_Filename) and bufferp("*Info*")) 631 { 632 widen(); 633 goto_line(n); bol(); 634 info_narrow(); 635 return; 636 } 637 638 if (strlen(split_file)) 639 { 640 setbuf(" *Info*"); 641 set_readonly(0); 642 widen(); 643 erase_buffer(); 644#ifndef VMS 645 variable ext = info_is_compressed (split_file); 646 if (strlen(ext)) 647 () = run_shell_cmd(sprintf("%s %s%s", make_unzip_cmd (ext), split_file, ext)); 648 else 649#endif 650 () = insert_file (split_file); 651 652 Info_Split_File_Buffer = whatbuf (); 653 setbuf ("*Info*"); 654 } 655 656 !if (strlen(file)) return; 657 info_find_file(file); 658 goto_line(n); bol(); 659 info_narrow(); 660} 661 662define info_next () 663{ 664 bob(); 665 !if (ffind("Next: ")) 666 { 667 info_goto_last_position (); 668 message ("Node has no NEXT."); 669 return; 670 } 671 go_right(6); push_mark(); 672 % comma, tab, or newline terminates 673 skip_chars ("^,.\t\n"); 674 %skip_chars("\d032-\d043\d045-\d255"); 675 bskip_chars(" "); 676 info_find_node(bufsubstr(())); 677} 678 679define info_quick_help() 680{ 681 message("q:quit, h:tutorial, SPC:next screen, DEL:prev screen, m:menu, s:search"); 682} 683 684 685$2 = "Infomap"; 686!if (keymap_p($2)) 687{ 688 make_keymap($2); 689 definekey("info_quick_help", "?", $2); 690 definekey("info_tutorial", "h", $2); 691 definekey("info_tutorial", "H", $2); 692 definekey("info_menu", "^M", $2); 693 definekey("info_menu", "M", $2); 694 definekey("info_menu", "m", $2); 695 696 definekey("info_next_xref", "\t", $2); 697#ifdef MSDOS MSWINDOWS 698 definekey("info_prev_xref", "^@^O", $2); 699#endif 700 701 definekey("info_next", "N", $2); 702 definekey("info_next", "n", $2); 703 definekey("info_prev", "P", $2); 704 definekey("info_prev", "p", $2); 705 definekey("info_up", "U", $2); 706 definekey("info_up", "u", $2); 707 definekey("page_down", " ", $2); 708 definekey("page_up", "^?", $2); 709 definekey("bob", "B", $2); 710 definekey("bob", "b", $2); 711 definekey("info_goto_node", "G", $2); 712 definekey("info_goto_node", "g", $2); 713 definekey("info_quit", "q", $2); 714 definekey("info_quit", "Q", $2); 715 definekey("info_goto_last_position", "l", $2); 716 definekey("info_goto_last_position", "L", $2); 717 definekey("info_search", "S", $2); 718 definekey("info_search", "s", $2); 719 definekey("info_search", "/", $2); 720 definekey("info_follow_reference", "f", $2); 721 definekey("info_follow_reference", "F", $2); 722 definekey("info_find_dir", "D", $2); 723 definekey("info_find_dir", "d", $2); 724 _for (1, 9, 1) 725 { 726 $1 = (); 727 definekey("info_menu_number", string($1), $2); 728 } 729} 730 731 732define info_quit () 733{ 734 info_record_position(); 735 widen(); 736 delbuf("*Info*"); 737} 738 739 740define info_goto_node() 741{ 742 info_find_node (read_mini("Node:", Null_String, Null_String)); 743} 744 745 746define info_search () 747{ 748 variable this_line, this_file, str, err_str, file, wline, ifile, ext; 749 err_str = "String not found."; 750 751 str = read_mini("Re-Search:", LAST_SEARCH, Null_String); 752 !if (strlen(str)) return; 753 save_search_string(str); 754 widen(); go_right_1 (); 755 if (re_fsearch(str)) 756 { 757 info_narrow(); 758 return; 759 } 760 761 % 762 % Not found. Look to see if this is split. 763 % 764 !if (strlen(Info_Split_File_Buffer)) 765 { 766 info_narrow(); 767 error (err_str); 768 } 769 770 this_file = Info_This_Filename; 771 this_line = what_line(); 772 wline = window_line(); %need this so state can be restored after a failure. 773 774 775 setbuf(Info_Split_File_Buffer); widen(); bob(); 776 bol_fsearch("Indirect:"); pop(); 777 push_mark(); 778 if (info_search_marker(1)) go_up_1 (); else eob(); 779 narrow(); 780 bob(); 781 bol_fsearch(extract_filename(this_file)); pop(); 782 783 ERROR_BLOCK 784 { 785 widen(); 786 info_find_file (this_file); 787 goto_line(this_line); eol(); 788 info_narrow(); 789 recenter(wline); 790 } 791 792 while (down_1 ()) 793 { 794 % bol(); --- implicit 795 push_mark(); 796 797 !if (ffind_char (':')) {pop_mark_0 (); break; } 798 file = bufsubstr(); 799 flush("Searching " + file); 800 (ifile, ext) = info_make_file_name(file); 801#ifdef UNIX OS2 802 if (strlen(ext)) 803 { 804 variable re = str; 805 806 % Not all greps support -e option. So, try this: 807 if (re[0] == '-') re = "\\" + re; 808 809 setbuf(" *Info*zcat*"); erase_buffer(); 810 811 () = run_shell_cmd(sprintf("%s %s%s | grep -ci '%s'", 812 make_unzip_cmd (ext), 813 ifile, ext, 814 re)); 815 bob(); 816 if (looking_at_char ('0')) 817 { 818 delbuf(whatbuf()); 819 setbuf(Info_Split_File_Buffer); 820 continue; 821 } 822 setbuf(Info_Split_File_Buffer); 823 } 824 else 825#endif 826 !if (search_file(ifile, str, 1)) 827 { 828 setbuf(Info_Split_File_Buffer); 829 continue; 830 } 831 832 info_find_file(file); 833 pop(fsearch(str)); 834 info_narrow(); 835 info_push_position(this_file, Info_Split_Filename, this_line); 836 return; 837 } 838 error (err_str); 839} 840 841define info_looking_at (ref) 842{ 843 variable n; 844 variable word; 845 846 push_spot (); 847 EXIT_BLOCK 848 { 849 pop_spot (); 850 } 851 ref = strcompress (ref, " "); 852 853 n = 0; 854 while (word = extract_element (ref, n, ' '), word != NULL) 855 { 856 n++; 857 skip_chars (" \t\n"); 858 !if (looking_at (word)) return 0; 859 go_right (strlen (word)); 860 } 861 1; 862} 863 864 865 866define info_follow_reference () 867{ 868 variable colon, colons, note, err, item, node, ref; 869 colon = ":"; colons = "::"; 870 note = "*Note"; 871 err = "No cross references."; 872 873 push_spot(); 874 !if (fsearch(note)) 875 { 876 !if (bsearch(note)) 877 { 878 pop_spot(); 879 error(err); 880 } 881 } 882 pop_spot(); 883 884 ref = read_mini("Follow *Note", Null_String, Null_String); 885 push_spot_bob (); 886 forever 887 { 888 !if (fsearch(note)) 889 { 890 pop_spot(); 891 error ("Bad reference."); 892 } 893 go_right (5); skip_chars (" \t\n"); 894 % skip_white(); 895 % if (eolp()) 896 % { 897 % go_right_1 (); skip_white(); 898 % } 899 if (info_looking_at(ref)) break; 900 } 901 902 push_mark(); 903 pop_spot(); 904 %info_record_position 905 pop_mark_1 (); 906 907 info_follow_current_xref (); 908} 909 910 911 912define info_menu_number () 913{ 914 variable node; node = Null_String; 915 variable colon, colons; 916 colons = "::"; colon = ":"; 917 variable n; 918 919 n = LAST_CHAR; 920 if ((n < '1') or (n > '9')) return (beep()); 921 n -= '0'; 922 923 info_find_menu(1); 924 925 while (n) 926 { 927 !if (bol_fsearch("* ")) return (beep()); 928 if (ffind(colon)) --n; else eol(); 929 } 930 931 if (looking_at(colons)) 932 { 933 push_mark(); 934 bol(); go_right(2); 935 } 936 else 937 { 938 go_right_1 (); skip_white(); push_mark(); 939 if (looking_at_char('(')) 940 { 941 () = ffind_char (')'); 942 } 943 % comma, tab, '.', or newline terminates 944 skip_chars ("^,.\t\n"); 945 %skip_chars("\d032-\d043\d045\d047-\d255"); 946 bskip_chars(" "); 947 } 948 info_find_node(bufsubstr(())); 949} 950 951 952 953define info_tutorial() 954{ 955 info_find_node("(info)help"); 956} 957 958private define start_info_reader () 959{ 960 variable ibuf; ibuf = "*Info*"; 961 if (Info_Stack_Depth) info_goto_last_position (); 962 !if (bufferp(ibuf)) info_find_dir(); 963 pop2buf(ibuf); 964 onewindow(); 965 if (0 == is_defined ("info_reader_hook")) 966 run_mode_hooks ("info_mode_hook"); 967 else 968 run_mode_hooks ("info_reader_hook"); 969} 970 971 972% Usage: 973% info_reader () 974% info_reader (args); 975% args[0] = file 976% args[1] = node 977define info_reader () 978{ 979 variable file, node; 980 981 start_info_reader (); 982 983 if (_NARGS == 0) 984 return; 985 986 variable args = (); 987 variable nargs = length (args); 988 989 local_setkey ("exit_jed", "q"); 990 local_setkey ("exit_jed", "Q"); 991 992 if (nargs > 0) 993 { 994 file = args[0]; 995 996#ifdef UNIX 997 if (path_basename (file) != file) 998 { 999 variable dir = path_dirname (file); 1000 file = path_basename (file); 1001 Info_Directory = strcat (dir, "," + Info_Directory); 1002 } 1003#endif 1004 % Goto top incase the requested node does not exist. 1005 info_find_node (sprintf ("(%s)top", file)); 1006 if (nargs > 1) 1007 info_find_node (sprintf ("(%s)%s", file, args[1])); 1008 } 1009} 1010