home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume17 / tcleditr / part09 < prev    next >
Encoding:
Text File  |  1992-03-17  |  46.8 KB  |  1,938 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!think.com!mips!msi!dcmartin
  3. From: crowley@chaco.cs.unm.edu (Charlie Crowley)
  4. Subject: v17i010: point text editor (TCL and TK), Part09/16
  5. Message-ID: <1992Mar18.141542.27063@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. References: <csx-17i002-tcl-editor@uunet.UU.NET>
  10. Date: Wed, 18 Mar 1992 14:15:42 GMT
  11. Approved: dcmartin@msi.com
  12.  
  13. Submitted-by: crowley@chaco.cs.unm.edu (Charlie Crowley)
  14. Posting-number: Volume 17, Issue 10
  15. Archive-name: tcl-editor/part09
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 8 (of 15)."
  24. # Contents:  browser.c regex.c
  25. # Wrapped by crowley@chaco.cs.unm.edu on Tue Mar 10 15:05:45 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'browser.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'browser.c'\"
  29. else
  30. echo shar: Extracting \"'browser.c'\" \(20828 characters\)
  31. sed "s/^X//" >'browser.c' <<'END_OF_FILE'
  32. X/* $Header: /nfs/unmvax/faculty/crowley/x/pt/RCS/browser.c,v 1.12 1992/03/04 17:07:18 crowley Exp crowley $ */
  33. X
  34. X#include <sys/types.h>
  35. X#include <string.h>
  36. X#include <stdio.h>
  37. X#include <stdlib.h>
  38. X#include "pt.h"
  39. X#ifdef SYSV
  40. X/*** NECESSARY? #include <libgen.h> ***/
  41. X#include <dirent.h>
  42. X#else
  43. X#include <sys/dir.h>
  44. X#endif
  45. X#include <sys/stat.h>
  46. X/***#include <stdio.h>***/
  47. X#include <X11/keysym.h>
  48. X#include <X11/StringDefs.h>
  49. X
  50. X
  51. X#define FILENAMESSIZE        10000
  52. X#define FILELISTSIZE         1000
  53. X#define FILETREECHARSIZE    10000
  54. X#define FILETREELISTSIZE     1000
  55. X#define HOME                1
  56. X#define N_OLD_DIRS           30
  57. X
  58. BrowserData *mainBrowser = NULL;
  59. BrowserData *activeBrowser = NULL;
  60. BrowserData *browserList = NULL;
  61. X
  62. X/* open window list data */
  63. OpenWindowStruct *openWindowList;
  64. int numberOfOpenWindows;
  65. X
  66. X/* cache of old directory data */
  67. int nextOldDirs = 0;
  68. XFileListData *oldDirs[N_OLD_DIRS];
  69. X
  70. X#ifdef VAX_FIX
  71. char *
  72. getcwd( buffer, length )
  73. X    char * buffer;
  74. X    int length;
  75. X{
  76. X    char *getwd();
  77. X
  78. X    return getwd( buffer );
  79. X}
  80. int
  81. isspace( c )
  82. X    char c;
  83. X{
  84. X    return c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f';
  85. X}
  86. double
  87. strtod( str, ptr )
  88. X    char * str;
  89. X    char ** ptr;
  90. X{
  91. X    double d = atof( str );
  92. X
  93. X    /* this is not exactly correct put will do for here */
  94. X    if( ptr != NULL )
  95. X        *ptr = str + strlen(str);
  96. X    return d;
  97. X}
  98. X#endif
  99. X
  100. static void
  101. InitializeDirectoryCache()
  102. X{
  103. X    int i;
  104. X    FileListData *fl;
  105. X    int size = sizeof(FileListData);
  106. X    
  107. X    for( i = 0; i < N_OLD_DIRS; ++i ) {
  108. X        fl = (FileListData *)PtMalloc( size, "list of files" );
  109. X        fl->fileNames = NULL;
  110. X        fl->listOfFilesShowing = NULL;
  111. X        fl->numberOfFilesShowing = 0;
  112. X        fl->ino = 0;
  113. X        fl->mtime = 0;
  114. X        fl->directoryName = NULL;
  115. X        fl->age = 0;
  116. X        fl->use_count = 0;
  117. X        fl->flags = 0;
  118. X        fl->filePattern[0] = '\0';
  119. X        oldDirs[i] = fl;
  120. X    }
  121. X}
  122. X
  123. BrowserData *
  124. XFindBrowserByTkName( name )
  125. X    char * name;
  126. X{
  127. X    extern BrowserData * browserList;
  128. X
  129. X    BrowserData * browser = browserList;
  130. X
  131. X    while( browser != NULL ) {
  132. X        if( strcmp( browser->tk_pathname, name ) == 0 )
  133. X            break;
  134. X        browser = browser->nextBrowser;
  135. X    }
  136. X    return browser;
  137. X}
  138. X
  139. void
  140. ReduceUseCount( fl )
  141. X    FileListData *fl;
  142. X{
  143. X    int i;
  144. X
  145. X    for( i = 0; i < N_OLD_DIRS; ++i ) {
  146. X        if( fl == oldDirs[i] ) {
  147. X            --(fl->use_count);
  148. X            break;
  149. X        }
  150. X    }
  151. X}
  152. X
  153. extern struct window *activeWindow;
  154. extern Display *MainDisplay;
  155. X
  156. X#ifdef LATERLATER
  157. void
  158. ptBrowserLetter(w, event, args, nargs)
  159. X    int w;
  160. X    XKeyEvent *event;
  161. X    String *args;
  162. X    Cardinal *nargs;
  163. X{
  164. X    extern char msgBuffer[];
  165. X    extern char * textGeometry;
  166. X    extern int debug;
  167. X
  168. X    char buf[4];
  169. X    int ret;
  170. X    KeySym keysym;
  171. X    static char prefix[100];
  172. X    static int iprefix = 0;
  173. X    static int last_index = -1;
  174. X
  175. X    if( event->type != KeyPress )
  176. X        return;
  177. X    ret = XLookupString(event, buf, 4, &keysym, NULL);
  178. X    buf[ret] = '\0';
  179. X    if( ret != 1 ) {
  180. X        switch( keysym ) {
  181. X        case XK_Shift_L:
  182. X        case XK_Shift_R:
  183. X        case XK_Control_L:
  184. X        case XK_Control_R:
  185. X        case XK_Caps_Lock:
  186. X        case XK_Shift_Lock:
  187. X        case XK_Meta_L:
  188. X        case XK_Meta_R:
  189. X        case XK_Alt_L:
  190. X        case XK_Alt_R:
  191. X        case XK_Super_L:
  192. X        case XK_Super_R:
  193. X        case XK_Hyper_L:
  194. X        case XK_Hyper_R:
  195. X            /* modifier keys, ignore them */
  196. X            return;
  197. X        }
  198. X    }
  199. X    if( ret == 1 ) {
  200. X        char **list = activeBrowser->fileListData->listOfFilesShowing;
  201. X        int num = activeBrowser->fileListData->numberOfFilesShowing;
  202. X        int i;
  203. X        if( buf[0] == '\r' ) {
  204. X            if( last_index != -1 ) {
  205. X#ifdef LATER
  206. X                OpenListFile( buf, textGeometry );
  207. X#endif
  208. X                printf("Unhighlight list item\n");
  209. X            } else if( iprefix == 0 ) {
  210. X                XBell( MainDisplay, 0 );
  211. X                printf("No file selected\n");
  212. X            } else {
  213. X                GetNewFile( NULL, prefix, textGeometry );
  214. X            }
  215. X        } else {
  216. X    startOver:
  217. X            prefix[iprefix++] = buf[0];
  218. X            prefix[iprefix] = '\0';
  219. X            for( i = 0; i < num; ++i ) {
  220. X                if( strncmp(prefix,list[i],iprefix) == 0 ) {
  221. X                    printf("Highlight list item\n");
  222. X                    last_index = i;
  223. X                    break;
  224. X                }
  225. X            }
  226. X            if( i >= num ) {
  227. X                last_index = -1;
  228. X                printf("Unhighlight list item\n");
  229. X            }
  230. X        }
  231. X    } else {
  232. X        iprefix = 0;
  233. X        last_index = -1;
  234. X        printf("Unhighlight list item\n");
  235. X    }
  236. X}
  237. X#endif
  238. X
  239. void
  240. ChangeBrowserFontTo( browser, fontName )
  241. X    BrowserData *browser;
  242. X    char *fontName;
  243. X{
  244. X    extern char msgBuffer[];
  245. X    extern Tcl_Interp * interp;
  246. X
  247. X    XFontStruct *fontInfo;
  248. X
  249. retry_font:
  250. X    fontInfo = Tk_GetFontStruct( interp, browser->tk_toplevel,
  251. X                        Tk_GetUid(fontName) );
  252. X    if( fontInfo == NULL ) {
  253. X        printf("Cannot load font %s, using \"fixed\"\n", fontName );
  254. X        fontName = "fixed";
  255. X        goto retry_font;
  256. X    }
  257. X    (browser->browserFont).height = fontInfo->ascent + fontInfo->descent;
  258. X    (browser->browserFont).width  = fontInfo->max_bounds.width;
  259. X    (browser->browserFont).ascent = fontInfo->ascent;
  260. X    Tk_FreeFontStruct( fontInfo );
  261. X
  262. X    sprintf( msgBuffer, "%s.fileList.list configure -font %s",
  263. X                    browser->tk_pathname, fontName );
  264. X    (void)ExecTclCommand( (char *)msgBuffer );
  265. X
  266. X    sprintf( msgBuffer, "%s.openList.list configure -font %s",
  267. X                    browser->tk_pathname, fontName );
  268. X    (void)ExecTclCommand( (char *)msgBuffer );
  269. X}
  270. X
  271. void
  272. RaiseListWindow( n, geometry )
  273. X    int n;
  274. X    char * geometry;
  275. X{
  276. X    extern char msgBuffer[];
  277. X
  278. X    struct window * w;
  279. X
  280. X    if( n < 0 || n >= numberOfOpenWindows ) {
  281. X        printf("MakeActiveWindow: index=%d should be < %d\n",
  282. X            n, numberOfOpenWindows );
  283. X        return;
  284. X    }
  285. X    w = openWindowList[n].w;
  286. X    if( w != NULL ) {
  287. X        activeWindow = w;
  288. X        sprintf( msgBuffer, "MoveWindow %s", geometry );
  289. X        (void)ExecTclCommand( (char *)msgBuffer );
  290. X    } else
  291. X        printf("ERROR: window %s not found in list of open windows\n",
  292. X            openWindowList[n].name);
  293. X}
  294. X
  295. int
  296. listComp( a, b )
  297. X    char *a;
  298. X    char *b;
  299. X{
  300. X    extern int showDirsFirst;
  301. X    extern int showSizes;
  302. X
  303. X    if( showDirsFirst ) {
  304. X        char last_in_a;
  305. X        char last_in_b;
  306. X        char * end_of_a = strlen(*(char **)a) - 1 + *(char **)a;
  307. X        char * end_of_b = strlen(*(char **)b) - 1 + *(char **)b;
  308. X        /* ignore the file size if present */
  309. X        if( showSizes ) {
  310. X            /* back up past the ' (NNNk)' */
  311. X            while( *end_of_a-- != ' ' )
  312. X                /*EMPTY*/
  313. X                ;
  314. X            while( *end_of_b-- != ' ' )
  315. X                /*EMPTY*/
  316. X                ;
  317. X        }
  318. X        /* get the last character in the file name */
  319. X        last_in_a = *end_of_a;
  320. X        last_in_b = *end_of_b;
  321. X        if( last_in_a == '/' ) {
  322. X            if( last_in_b != '/' )
  323. X                return -1;
  324. X        } else {
  325. X            if( last_in_b == '/' )
  326. X                return 1;
  327. X        }
  328. X    }
  329. X    return strcmp(*(char **)a, *(char **)b);
  330. X}
  331. X
  332. int
  333. openComp( a, b )
  334. X    char *a;
  335. X    char *b;
  336. X{
  337. X    return strcmp(  ((OpenWindowStruct *)a)->name,
  338. X            ((OpenWindowStruct *)b)->name );
  339. X}
  340. X
  341. X#ifdef SVR4
  342. X#undef SYSV
  343. X#define SYSV
  344. X#endif
  345. X
  346. X/*SUPPRESS 68*/ /*SUPPRESS 544*/
  347. X
  348. void
  349. NewFilelist( browser )
  350. X    BrowserData *browser;
  351. X{
  352. X    extern char * filePattern;
  353. X    extern char msgBuffer[];
  354. X    extern char textBuffer[];
  355. X    extern char currentDirectory[];
  356. X    extern int showSizes;
  357. X    extern int debug;
  358. X
  359. X    DIR *dirp;
  360. X#ifdef SYSV
  361. X    struct dirent *dp;
  362. X#else
  363. X    struct direct *dp;
  364. X#endif
  365. X    int namelength;
  366. X    char *endFileNames, *curFileNames;
  367. X    char **endList, **curList;
  368. X    int wide;
  369. X    struct stat statbuf;
  370. X    int nCols;
  371. X    int longestName;
  372. X    int i, col, oldest_unused, oldest_age, new_dir;
  373. X    char *p;
  374. X    char *pp;
  375. X    FileListData *fl;
  376. X    char flags;
  377. X    char buffer[256];
  378. X    char * from, * to, * re_bad;
  379. X
  380. X    /* to save computation keep local copies of these */
  381. X    char *fileNames;
  382. X    char **listOfFilesShowing;
  383. X    int numberOfFilesShowing;
  384. X
  385. X    /* protect myself (this happens during initialization) */
  386. X    if( browser == NULL )
  387. X        return;
  388. X    /* make up the flags byte */
  389. X    flags = 0;
  390. X    if( showSizes )
  391. X        flags |= SHOW_SIZES_FLAG;
  392. X
  393. X    /* get the current directory and change the label to display it */
  394. X    (void)getcwd(currentDirectory, FILENAMESIZE);
  395. X    strncpy(browser->cwd, currentDirectory, FILENAMESIZE);
  396. X
  397. X    /* see if this directory is in our cache (and has not changed) */
  398. X    stat( currentDirectory, &statbuf );    /* get inode and mtime */
  399. X    oldest_unused = 0;    /* always have a legal value */
  400. X    oldest_age = -1;
  401. X    new_dir = -1;
  402. X    for( i = 0; i < N_OLD_DIRS; ++i ) {
  403. X        fl = oldDirs[i];    /* constantly used so get ptr */
  404. X        /* increment the age and look for the oldest, unused one */
  405. X        ++(fl->age);
  406. X        if( fl->use_count == 0 && fl->age > oldest_age ) {
  407. X            oldest_age = fl->age;
  408. X            oldest_unused = i;
  409. X        }
  410. X        /* look for the old directory in the cache */
  411. X        if( fl == browser->fileListData ) {
  412. X            --(fl->use_count);
  413. X        }
  414. X        /* if this directory is in the cache and unchanged, use it */
  415. X        if( fl->ino==statbuf.st_ino && fl->mtime==statbuf.st_mtime
  416. X         && fl->flags==flags && fl->showSizes==showSizes
  417. X         && strcmp(fl->filePattern,filePattern)==0 ) {
  418. X             fl->age = 0;    /* restart aging */
  419. X             ++(fl->use_count);    /* another user of this one */
  420. X             new_dir = i;
  421. X         }
  422. X    }
  423. X    if( new_dir >= 0 ) {    /* found it in the cache */
  424. X        fl = oldDirs[new_dir];
  425. X        browser->fileListData = fl;
  426. X        longestName = fl->longestname;
  427. X        listOfFilesShowing = fl->listOfFilesShowing;
  428. X        numberOfFilesShowing = fl->numberOfFilesShowing;
  429. X        goto changeDisplay;
  430. X    }
  431. X    /* else erase the oldest entry in the directory cache, */
  432. X    fl = oldDirs[oldest_unused];
  433. X
  434. X    /* free the strings whose pointers we will write over */
  435. X    PtFree( fl->fileNames );
  436. X    PtFree( (char *)(fl->listOfFilesShowing) );
  437. X    PtFree( fl->directoryName );
  438. X
  439. X    /* initialize the fields */
  440. X    browser->fileListData = fl;
  441. X    fl->age = 0;
  442. X    fl->use_count = 1;
  443. X    fl->ino = statbuf.st_ino;
  444. X    fl->mtime = statbuf.st_mtime;
  445. X    fl->flags = flags;
  446. X    strncpy( fl->filePattern, filePattern, 128 );
  447. X
  448. X    /* remember the directory name */
  449. X    p = (char *)PtMalloc( strlen(currentDirectory)+1, "directory name" );
  450. X    strcpy( p, currentDirectory );
  451. X    fl->directoryName = (char *)p;
  452. X    
  453. X    /* allocate the space for the lists */
  454. X    fileNames = PtMalloc(FILENAMESSIZE*sizeof(char), "file names" );
  455. X    endFileNames = fileNames + FILENAMESSIZE;
  456. X    curFileNames = fileNames;
  457. X    listOfFilesShowing = (char **)PtMalloc(FILELISTSIZE*sizeof(char *),
  458. X                        (char *)"files showing" );
  459. X    endList = listOfFilesShowing + FILELISTSIZE;
  460. X    curList = listOfFilesShowing;
  461. X
  462. X    /* set up the regular expression to check the filenames against */
  463. X    to = buffer;
  464. X    from = fl->filePattern;
  465. X    *to++ = '^';
  466. X    while( 1 ) {
  467. X        char ch = *from++;
  468. X        switch( ch ) {
  469. X            case '\0':
  470. X                *to++ = '$';
  471. X                *to = '\0';
  472. X                goto out;
  473. X            case '*':
  474. X                *to++ = '.';
  475. X                break;
  476. X            case '?':
  477. X                ch = '.';
  478. X                break;
  479. X            case '.':
  480. X                *to++ = '\\';
  481. X                break;
  482. X        }
  483. X        *to++ = ch;
  484. X    }
  485. out:
  486. X    if( (re_bad = re_comp(buffer)) != NULL ) {
  487. X        printf("RE error: %s\n", re_bad);
  488. X    }
  489. X    
  490. X    dirp = opendir(".");
  491. X    if( dirp == NULL ) {
  492. X        extern int errno;
  493. X        extern int sys_nerr;
  494. X        extern char *sys_errlist[];
  495. X        if( errno < sys_nerr )
  496. X            p = (char *)sys_errlist[errno];
  497. X        else
  498. X            p = (char *)"";
  499. X        sprintf( msgBuffer, "Open directory failed: %s", (char *)p );
  500. X        msg( (char *)msgBuffer, 1 );
  501. X        *curList = "Could not open directory";
  502. X        longestName = strlen(*curList);
  503. X        numberOfFilesShowing = 1;
  504. X        goto skipDirectorySearch;
  505. X    }
  506. X    /* put in the Tk command */
  507. X    numberOfFilesShowing = 0;
  508. X    longestName = 0;
  509. X    dp = readdir(dirp);    /* skip '.' (which is always first) */
  510. X    for( dp = readdir(dirp); dp != NULL; dp = readdir(dirp) ) {
  511. X#ifdef SYSV
  512. X        namelength = strlen(dp->d_name);
  513. X#else
  514. X        namelength = dp->d_namlen;
  515. X#endif
  516. X        stat(dp->d_name, &statbuf);
  517. X        if( (statbuf.st_mode & S_IFMT)!=S_IFDIR &&  re_bad==NULL ) {
  518. X            i = re_match( dp->d_name );
  519. X            if( i < 1 ) {
  520. printf(" (NoMatch %s)", dp->d_name);
  521. X                continue;
  522. X            }
  523. X        }
  524. X        if( curFileNames + namelength >= endFileNames ) {
  525. X            printf("name list overflow\n");
  526. X/* LATER REALLOCATE THE LIST LARGER */
  527. X            break;
  528. X        }
  529. X        if( curList >= endList ) {
  530. X            printf("pointer list overflow\n");
  531. X            /* later reallocate the list larger */
  532. X            break;
  533. X        }
  534. X        *curList++ = curFileNames;
  535. X        strcpy(curFileNames, dp->d_name);
  536. X        curFileNames += namelength + 1;    /* +1 for the nul */
  537. X        if( (statbuf.st_mode & S_IFMT) == S_IFDIR ) {
  538. X            *--curFileNames = '/';
  539. X            *++curFileNames = '\0';
  540. X            ++curFileNames;
  541. X            ++(namelength);
  542. X        }
  543. X        if( showSizes ) {
  544. X            char s[25];
  545. X            int i, l;
  546. X            sprintf( s, " (%dk)", (statbuf.st_size+1023)/1024 );
  547. X            l = strlen( s );
  548. X            --curFileNames;        /* back up over the '\0' */
  549. X            for( i = 0; i <= l; ++i ) {
  550. X                *curFileNames++ = s[i];
  551. X            }
  552. X            /* this loop will copy the '\0' also */
  553. X            namelength += l;
  554. X        }
  555. X        if( namelength > longestName )
  556. X            longestName = namelength;
  557. X        ++numberOfFilesShowing;
  558. X    }
  559. X    closedir(dirp);
  560. X
  561. X    /* sort the file names */
  562. X    qsort( (char *)listOfFilesShowing, numberOfFilesShowing,
  563. X            sizeof(char *), listComp);
  564. X
  565. skipDirectorySearch:
  566. X    /* put everything back into the structure */
  567. X    fl->fileNames = fileNames;
  568. X    fl->listOfFilesShowing = listOfFilesShowing;
  569. X    fl->numberOfFilesShowing = numberOfFilesShowing;
  570. X    fl->longestname = longestName;
  571. X    fl->showSizes = showSizes;
  572. X
  573. changeDisplay:
  574. X    /* figure out how many columns to use */
  575. X        /* for big browsers only */
  576. X    {
  577. X        int columnSpacing = 7;
  578. X        int overhead = 46;
  579. X
  580. X        wide = Tk_Width( browser->tk_toplevel ) - overhead;
  581. X        col = longestName*((browser->browserFont).width)+columnSpacing;
  582. X        nCols = (wide + columnSpacing) / col;
  583. X        if( nCols < 1 )
  584. X            nCols = 1;
  585. X        sprintf(msgBuffer,"%s.fileList.list configure -columns %d",
  586. X                        browser->tk_pathname, nCols );
  587. X        (void)ExecTclCommand( (char *)msgBuffer );
  588. X    }
  589. X
  590. X    /* make this the new list */
  591. X    /* first delete all the old list elements */
  592. X    sprintf( msgBuffer, "catch {%s.fileList.list delete 0 end}",
  593. X                            browser->tk_pathname );
  594. X    (void)ExecTclCommand( (char *)msgBuffer );
  595. X    
  596. X    /* then insert each file name in the new list */
  597. X    for( i = 0; i < numberOfFilesShowing; ++i ) {
  598. X        sprintf( msgBuffer, "%s.fileList.list insert end \"%s\"",
  599. X                browser->tk_pathname, listOfFilesShowing[i] );
  600. X        (void)ExecTclCommand( (char *)msgBuffer );
  601. X    }
  602. X
  603. X    /* store the directory name in the window title */
  604. X    strcpy( msgBuffer, browser->cwd );
  605. X    pp = tildefyFilename( (char *)msgBuffer );
  606. X    sprintf( textBuffer,
  607. X        "wm title %s {%s};wm iconname %s {%s}",
  608. X            browser->tk_pathname, pp, browser->tk_pathname, pp );
  609. X    (void)ExecTclCommand( textBuffer );
  610. X}
  611. X
  612. void
  613. NewOpenList( )
  614. X{
  615. X    extern struct openFile *files;
  616. X    extern struct window *windowList;
  617. X    extern char msgBuffer[];
  618. X    extern int pathNames;
  619. X    extern int debug;
  620. X    extern struct openFile *files;
  621. X    extern BrowserData *browserList;
  622. X
  623. X    int col;
  624. X    int n, wide, nCols, len, longestName;
  625. X    struct window *w;
  626. X    char *s, *new_s;
  627. X    BrowserData *browser;
  628. X
  629. X    /* free the old space first */
  630. X    if( openWindowList != NULL ) {
  631. X        int i = 0;
  632. X        OpenWindowStruct *sp = openWindowList;
  633. X        while( i++ < numberOfOpenWindows )
  634. X            PtFree( (sp++)->name );
  635. X        PtFree((char *)openWindowList);
  636. X    }
  637. X        
  638. X    /* see how many windows there are */
  639. X    w = windowList;
  640. X    numberOfOpenWindows = 0;
  641. X    while( w != NULL ) {
  642. X        ++numberOfOpenWindows;
  643. X        w = w->nextWindow;
  644. X    }
  645. X
  646. X    /* always have at least one space in openWindowList */
  647. X    if( (n = numberOfOpenWindows) == 0 )
  648. X        n = 1;
  649. X    openWindowList = (OpenWindowStruct *) PtMalloc(
  650. X            n * sizeof(OpenWindowStruct), "open window list" );
  651. X
  652. X    if( numberOfOpenWindows > 0 ) {
  653. X        w = windowList;
  654. X        longestName = 0;
  655. X        n = 0;
  656. X        while( n < numberOfOpenWindows ) {
  657. X            /* see if we should use the full pathname */
  658. X            col = (pathNames ? 0 : w->nameOffset);
  659. X            s = &((files[w->fileId].origName)[col]);
  660. X            len = strlen(s) + 2;
  661. X            /* allocate space for the name and copy it in */
  662. X            new_s = (char *)PtMalloc(len, "file name");
  663. X            strncpy( new_s, s, len );
  664. X            if( files[w->fileId].flags & IS_CHANGED ) {
  665. X                /* if changed add a '*' at the end */
  666. X                --len;    /* we added one for the '\0' */
  667. X                new_s[len-1] = '*';
  668. X                new_s[len] = '\0';
  669. X            } else
  670. X                /* otherwise correct the length */
  671. X                len -= 2;
  672. X            openWindowList[n].name = new_s;
  673. X            if( len > longestName )
  674. X                longestName = len;
  675. X            /* remember the window ID so we can raise it easily */
  676. X            openWindowList[n].w = w;
  677. X            w = w->nextWindow;
  678. X            ++n;
  679. X        }
  680. X        qsort( (char *)openWindowList, numberOfOpenWindows,
  681. X                sizeof(OpenWindowStruct), openComp );
  682. X    
  683. X    } else {
  684. X#define NO_WINDOWS "No Open Windows"
  685. X        s = (char *)PtMalloc( strlen(NO_WINDOWS)+1, "file name" );
  686. X        strcpy( s, NO_WINDOWS );
  687. X#undef NO_WINDOWS
  688. X        openWindowList[numberOfOpenWindows].w = NULL;
  689. X        openWindowList[numberOfOpenWindows++].name = s;
  690. X        longestName = strlen(s);
  691. X    }
  692. X
  693. X    /* loop through all the browsers and change their open lists */
  694. X    for( browser = browserList; browser != NULL;
  695. X                    browser = browser->nextBrowser) {
  696. X        int columnSpacing = 7;
  697. X
  698. X        if( browser->tk_pathname[0] == '\0' )
  699. X            /* main browser was not created, so skip it */
  700. X            continue;
  701. X        /* make this the new list */
  702. X        /* first delete all the old list elements */
  703. X        sprintf( msgBuffer, "catch {%s.openList.list delete 0 end}",
  704. X                            browser->tk_pathname );
  705. X        (void)ExecTclCommand( (char *)msgBuffer );
  706. X
  707. X        /* then insert each file name in the new list */
  708. X        for( n = 0; n < numberOfOpenWindows; ++n ) {
  709. X            sprintf( msgBuffer, "%s.openList.list insert end {%s}",
  710. X                browser->tk_pathname, openWindowList[n].name );
  711. X            (void)ExecTclCommand( (char *) msgBuffer );
  712. X        }
  713. X
  714. X        wide = Tk_Width( browser->tk_toplevel ) - 50;
  715. X        col = longestName*((browser->browserFont).width)+columnSpacing;
  716. X        nCols = (wide + columnSpacing) / col;
  717. X        if( nCols < 1 )
  718. X            nCols = 1;
  719. X        sprintf(msgBuffer,"%s.openList.list configure -columns %d",
  720. X                        browser->tk_pathname, nCols );
  721. if( debug == 0 )
  722. X        (void)ExecTclCommand( (char *) msgBuffer );
  723. X    }
  724. X
  725. X}
  726. X
  727. void
  728. CreateNewBrowser( bigBrowser, geometry )
  729. X    int bigBrowser;
  730. X    char * geometry;
  731. X{
  732. X    extern struct window *windowList;
  733. X    extern int debug;
  734. X    extern int thinBrowser;
  735. X
  736. X    BrowserData *browser;
  737. X
  738. X    /* create the browser data structure */
  739. X    browser = (BrowserData *)PtMalloc(sizeof(BrowserData),"browser data");
  740. X    browser->fileListData = NULL; /* this is allocated in NewFilelist */
  741. X
  742. X    thinBrowser = !bigBrowser;
  743. X
  744. X    /* put on the browserList */
  745. X    browser->nextBrowser = browserList;
  746. X    browser->prevBrowser = NULL;
  747. X    browserList->prevBrowser = browser;
  748. X    browserList = browser;
  749. X    browser->tk_toplevel = NULL;
  750. X    CreateBigBrowser( browser, geometry );
  751. X}
  752. X
  753. void
  754. CreateBigBrowser( browser, geometry )
  755. X    BrowserData *browser;
  756. X    char * geometry;
  757. X{
  758. X    extern BrowserData *activeBrowser;
  759. X    extern char msgBuffer[];
  760. X    extern char * browserFont;
  761. X    extern Tcl_Interp * interp;
  762. X    extern int debug;
  763. X
  764. X    char * name;
  765. X
  766. X    sprintf (msgBuffer, "BrowserWindow %s", geometry );
  767. X    name = ExecTclCommand( (char *)msgBuffer );
  768. X    browser->tk_pathname = Tk_GetUid( name );
  769. X    browser->tk_toplevel = Tk_NameToWindow( interp, browser->tk_pathname,
  770. X                        mainBrowser->tk_toplevel );
  771. X
  772. X    Tk_SetWindowBackground( browser->tk_toplevel,
  773. X            WhitePixelOfScreen(Tk_Screen(browser->tk_toplevel)));
  774. X    XSetForeground( Tk_Display(browser->tk_toplevel),
  775. X            DefaultGCOfScreen(Tk_Screen(browser->tk_toplevel)),
  776. X            BlackPixelOfScreen(Tk_Screen(browser->tk_toplevel)));
  777. X            
  778. X    ChangeBrowserFontTo( browser, browserFont );
  779. X
  780. X    activeBrowser = browser;
  781. X    (void)ExecTclCommand( "update" );
  782. X    NewOpenList();
  783. X
  784. X    /* Now create the list of files */
  785. X    NewFilelist( browser );
  786. X}
  787. X
  788. Tk_Window TkMainWindow;
  789. X
  790. void
  791. CreateFilelist()
  792. X{
  793. X    extern Tcl_Interp * interp;
  794. X    extern int Pt_ColboxCmd();
  795. X    extern char * browserGeometry;
  796. X    extern char * thinBrowserGeometry;
  797. X    extern int noBrowser;
  798. X    extern int thinBrowser;
  799. X    extern char msgBuffer[];
  800. X
  801. X    Tk_Uid uid;
  802. X
  803. X    InitializeDirectoryCache();
  804. X
  805. X    /* create the browser data structure */
  806. X    mainBrowser = (BrowserData *)PtMalloc( sizeof(BrowserData),
  807. X                        "browser data" );
  808. X    mainBrowser->fileListData = NULL; /* this is allocated in NewFileList */
  809. X    numberOfOpenWindows = 0;
  810. X    openWindowList = NULL;
  811. X
  812. X    /* make this the only entry in the browserList */
  813. X    mainBrowser->nextBrowser = NULL;
  814. X    mainBrowser->prevBrowser = NULL;
  815. X    browserList = mainBrowser;
  816. X
  817. X    /* finish creating the browser */
  818. X    /* create the main tcl interpreter and add the Point commands */
  819. X    interp = Tcl_CreateInterp();
  820. X    AddPointCommands( interp );
  821. X    
  822. X    /* create the main window and set up some options */
  823. X    TkMainWindow = Tk_CreateMainWindow( interp, (char *) NULL, "point");
  824. X    mainBrowser->tk_toplevel = TkMainWindow;
  825. X    if( mainBrowser->tk_toplevel == NULL ) {
  826. X        printf("%s\n", interp->result);
  827. X        exit(1);
  828. X    }
  829. X
  830. X    Tk_SetClass( mainBrowser->tk_toplevel, "Point");
  831. X
  832. X    /* check the user's default font, foreground and background. */
  833. X    /* Use those if they are defined */
  834. X    uid = Tk_GetOption( mainBrowser->tk_toplevel, "font", NULL );
  835. X    if( uid == NULL )
  836. X        uid = Tk_GetOption( mainBrowser->tk_toplevel, "Font", NULL );
  837. X    if( uid != NULL ) {
  838. X        SetPointOption( "browserFont", uid );
  839. X        SetPointOption( "textFont", uid );
  840. X    }
  841. X    uid = Tk_GetOption( mainBrowser->tk_toplevel, "foreground", NULL );
  842. X    if( uid != NULL )
  843. X        SetPointOption( "textForeground", uid );
  844. X    uid = Tk_GetOption( mainBrowser->tk_toplevel, "background", NULL );
  845. X    if( uid != NULL )
  846. X        SetPointOption( "textBackground", uid );
  847. X
  848. X    Tcl_CreateCommand( interp, "colbox", Pt_ColboxCmd,
  849. X            (ClientData)(mainBrowser->tk_toplevel), NULL );
  850. X
  851. X    /* read in the Point proc's and create a browser window */
  852. X    sprintf( msgBuffer,
  853. X"global PointTclLibrary\n\
  854. set PointTclLibrary \"%s\"\n\
  855. if [file exists $PointTclLibrary/startup.tcl] \"\n\
  856. X    source $PointTclLibrary/startup.tcl\n\
  857. X\" {puts stderr \"CANNOT FIND A STARTUP FILE. POINT WILL NOT WORK.\"}",
  858. X        POINT_LIBRARY );
  859. X    (void)ExecTclCommand( msgBuffer );
  860. X
  861. X    (void)ExecTclCommand( "if [file exists .ptdirrc] {source .ptdirrc}" );
  862. X    Tk_MakeWindowExist( mainBrowser->tk_toplevel );
  863. X    mainBrowser->tk_pathname = "";
  864. X    if( !noBrowser )
  865. X        CreateNewBrowser( !thinBrowser,
  866. X            (thinBrowser ? thinBrowserGeometry : browserGeometry));
  867. X}
  868. X
  869. END_OF_FILE
  870. if test 20828 -ne `wc -c <'browser.c'`; then
  871.     echo shar: \"'browser.c'\" unpacked with wrong size!
  872. fi
  873. # end of 'browser.c'
  874. fi
  875. if test -f 'regex.c' -a "${1}" != "-c" ; then 
  876.   echo shar: Will not clobber existing file \"'regex.c'\"
  877. else
  878. echo shar: Extracting \"'regex.c'\" \(22890 characters\)
  879. sed "s/^X//" >'regex.c' <<'END_OF_FILE'
  880. X#ifdef uts
  881. X#include <ctype.h>
  882. X#endif /* uts */
  883. X#include "pt.h"
  884. X/*
  885. X * These routines are BSD regex(3)/ed(1) compatible regular-expression
  886. X * routines written by Ozan S. Yigit, Computer Science, York University.
  887. X * Parts of the code that are not needed by Prospero have been removed,
  888. X * but most of the accompanying information has been left intact. 
  889. X * This file is to be included on those operating systems that do not
  890. X * support re_comp and re_exec.
  891. X */
  892. X
  893. X/*
  894. X * regex - Regular expression pattern matching
  895. X *         and replacement
  896. X *
  897. X * by:  Ozan S. Yigit (oz@nexus.yorku.ca)
  898. X *      York University
  899. X *
  900. X * These routines are the PUBLIC DOMAIN equivalents 
  901. X * of regex routines as found in 4.nBSD UN*X, with minor
  902. X * extensions.
  903. X *
  904. X * Modification history:
  905. X *
  906. X * $Log: regex.c,v $
  907. X * Revision 1.3  1992/03/04  17:07:18  crowley
  908. X * Backup
  909. X *
  910. X * Revision 1.2  1992/02/19  19:56:49  crowley
  911. X * Backup
  912. X *
  913. X * Revision 1.1  1992/02/19  16:43:42  crowley
  914. X * Backup
  915. X *
  916. X * Revision 1.3  89/04/01  14:18:09  oz
  917. X * Change all references to a dfa: this is actually an nfa.
  918. X * 
  919. X * Revision 1.2  88/08/28  15:36:04  oz
  920. X * Use a complement bitmap to represent NCL.
  921. X * This removes the need to have seperate 
  922. X * code in the pmatch case block - it is 
  923. X * just CCL code now.
  924. X * 
  925. X * Use the actual CCL code in the CLO
  926. X * section of pmatch. No need for a recursive
  927. X * pmatch call.
  928. X * 
  929. X * Use a bitmap table to set char bits in an
  930. X * 8-bit chunk.
  931. X * 
  932. X * Routines:
  933. X *      re_comp:        compile a regular expression into
  934. X *                      a NFA.
  935. X *
  936. X *            char *re_comp(s)
  937. X *            char *s;
  938. X *
  939. X *      re_exec:        execute the NFA to match a pattern.
  940. X *
  941. X *            int re_exec(s)
  942. X *            char *s;
  943. X *
  944. X * Regular Expressions:
  945. X *
  946. X *      [1]     char    matches itself, unless it is a special
  947. X *                      character (metachar): . \ [ ] * + ^ $
  948. X *
  949. X *      [2]     .       matches any character.
  950. X *
  951. X *      [3]     \       matches the character following it, except
  952. X *            when followed by a left or right round bracket,
  953. X *            a digit 1 to 9 or a left or right angle bracket. 
  954. X *            (see [7], [8] and [9])
  955. X *            It is used as an escape character for all 
  956. X *            other meta-characters, and itself. When used
  957. X *            in a set ([4]), it is treated as an ordinary
  958. X *            character.
  959. X *
  960. X *      [4]     [set]   matches one of the characters in the set.
  961. X *                      If the first character in the set is "^",
  962. X *                      it matches a character NOT in the set, i.e. 
  963. X *            complements the set. A shorthand S-E is 
  964. X *            used to specify a set of characters S upto 
  965. X *            E, inclusive. The special characters "]" and 
  966. X *            "-" have no special meaning if they appear 
  967. X *            as the first chars in the set.
  968. X *                      examples:        match:
  969. X *
  970. X *                              [a-z]    any lowercase alpha
  971. X *
  972. X *                              [^]-]    any char except ] and -
  973. X *
  974. X *                              [^A-Z]   any char except uppercase
  975. X *                                       alpha
  976. X *
  977. X *                              [a-zA-Z] any alpha
  978. X *
  979. X *      [5]     *       any regular expression form [1] to [4], followed by
  980. X *                      closure char (*) matches zero or more matches of
  981. X *                      that form.
  982. X *
  983. X *      [6]     +       same as [5], except it matches one or more.
  984. X *
  985. X *      [7]             a regular expression in the form [1] to [10], enclosed
  986. X *                      as \(form\) matches what form matches. The enclosure
  987. X *                      creates a set of tags, used for [8] and for
  988. X *                      pattern substution. The tagged forms are numbered
  989. X *            starting from 1.
  990. X *
  991. X *      [8]             a \ followed by a digit 1 to 9 matches whatever a
  992. X *                      previously tagged regular expression ([7]) matched.
  993. X *
  994. X *    [9]    \<    a regular expression starting with a \< construct
  995. X *        \>    and/or ending with a \> construct, restricts the
  996. X *            pattern matching to the beginning of a word, and/or
  997. X *            the end of a word. A word is defined to be a character
  998. X *            string beginning and/or ending with the characters
  999. X *            A-Z a-z 0-9 and _. It must also be preceded and/or
  1000. X *            followed by any character outside those mentioned.
  1001. X *
  1002. X *      [10]            a composite regular expression xy where x and y
  1003. X *                      are in the form [1] to [10] matches the longest
  1004. X *                      match of x followed by a match for y.
  1005. X *
  1006. X *      [11]    ^    a regular expression starting with a ^ character
  1007. X *        $    and/or ending with a $ character, restricts the
  1008. X *                      pattern matching to the beginning of the line,
  1009. X *                      or the end of line. [anchors] Elsewhere in the
  1010. X *            pattern, ^ and $ are treated as ordinary characters.
  1011. X *
  1012. X *
  1013. X * Acknowledgements:
  1014. X *
  1015. X *    HCR's Hugh Redelmeier has been most helpful in various
  1016. X *    stages of development. He convinced me to include BOW
  1017. X *    and EOW constructs, originally invented by Rob Pike at
  1018. X *    the University of Toronto.
  1019. X *
  1020. X * References:
  1021. X *              Software tools            Kernighan & Plauger
  1022. X *              Software tools in Pascal        Kernighan & Plauger
  1023. X *              Grep [rsx-11 C dist]            David Conroy
  1024. X *        ed - text editor        Un*x Programmer's Manual
  1025. X *        Advanced editing on Un*x    B. W. Kernighan
  1026. X *        regexp routines            Henry Spencer
  1027. X *
  1028. X * Notes:
  1029. X *
  1030. X *    This implementation uses a bit-set representation for character
  1031. X *    classes for speed and compactness. Each character is represented 
  1032. X *    by one bit in a 128-bit block. Thus, CCL always takes a 
  1033. X *    constant 16 bytes in the internal nfa, and re_exec does a single
  1034. X *    bit comparison to locate the character in the set.
  1035. X *
  1036. X * Examples:
  1037. X *
  1038. X *    pattern:    foo*.*
  1039. X *    compile:    CHR f CHR o CLO CHR o END CLO ANY END END
  1040. X *    matches:    fo foo fooo foobar fobar foxx ...
  1041. X *
  1042. X *    pattern:    fo[ob]a[rz]    
  1043. X *    compile:    CHR f CHR o CCL bitset CHR a CCL bitset END
  1044. X *    matches:    fobar fooar fobaz fooaz
  1045. X *
  1046. X *    pattern:    foo\\+
  1047. X *    compile:    CHR f CHR o CHR o CHR \ CLO CHR \ END END
  1048. X *    matches:    foo\ foo\\ foo\\\  ...
  1049. X *
  1050. X *    pattern:    \(foo\)[1-3]\1    (same as foo[1-3]foo)
  1051. X *    compile:    BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
  1052. X *    matches:    foo1foo foo2foo foo3foo
  1053. X *
  1054. X *    pattern:    \(fo.*\)-\1
  1055. X *    compile:    BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
  1056. X *    matches:    foo-foo fo-fo fob-fob foobar-foobar ...
  1057. X * 
  1058. X */
  1059. X
  1060. X#define MAXNFA  1024
  1061. X#define MAXTAG  10
  1062. X
  1063. X#define OKP     1
  1064. X#define NOP     0
  1065. X
  1066. X#define CHR     1
  1067. X#define ANY     2
  1068. X#define CCL     3
  1069. X#define BOL     4
  1070. X#define EOL     5
  1071. X#define BOT     6
  1072. X#define EOT     7
  1073. X#define BOW    8
  1074. X#define EOW    9
  1075. X#define REF     10
  1076. X#define CLO     11
  1077. X#define CHR2    12
  1078. X    /* two characters (for case insensitive search) */
  1079. X
  1080. X#define END     0
  1081. X
  1082. X/*
  1083. X * The following defines are not meant
  1084. X * to be changeable. They are for readability
  1085. X * only.
  1086. X *
  1087. X */
  1088. X#define MAXCHR    128
  1089. X#define CHRBIT    8
  1090. X#define BITBLK    MAXCHR/CHRBIT
  1091. X#define BLKIND    0170
  1092. X#define BITIND    07
  1093. X
  1094. X#define ASCIIB    0177
  1095. X
  1096. typedef /*unsigned*/ char CHAR;
  1097. X
  1098. static int  tagstk[MAXTAG];             /* subpat tag stack..*/
  1099. static CHAR nfa[MAXNFA];        /* automaton..       */
  1100. static int  sta = NOP;                   /* status of lastpat */
  1101. X
  1102. static CHAR bittab[BITBLK];        /* bit table for CCL */
  1103. X                    /* pre-set bits...   */
  1104. static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
  1105. X
  1106. static int internal_error;
  1107. X
  1108. static void
  1109. chset(c)
  1110. register CHAR c;
  1111. X{
  1112. X    bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
  1113. X}
  1114. X
  1115. X#define badpat(x)    return (*nfa = END, x)
  1116. X#define store(x)    *mp++ = x
  1117. char *     
  1118. re_comp(pat)
  1119. char *pat;
  1120. X{
  1121. X    extern int ignoreCase;
  1122. X    register char *p;               /* pattern pointer   */
  1123. X    register CHAR *mp = nfa;        /* nfa pointer       */
  1124. X    register CHAR *lp;              /* saved pointer..   */
  1125. X    register CHAR *sp = nfa;        /* another one..     */
  1126. X
  1127. X    register int tagi = 0;          /* tag stack index   */
  1128. X    register int tagc = 1;          /* actual tag count  */
  1129. X
  1130. X    register int n;
  1131. X    register CHAR mask;        /* xor mask -CCL/NCL */
  1132. X    int c1, c2;
  1133. X    char ch;
  1134. X        
  1135. X    if (!pat || !*pat)
  1136. X        if (sta)
  1137. X            return 0;
  1138. X        else
  1139. X            badpat("No previous regular expression");
  1140. X    sta = NOP;
  1141. X
  1142. X    for (p = pat; *p; p++) {
  1143. X        lp = mp;
  1144. X        switch(*p) {
  1145. X
  1146. X        case '.':               /* match any char..  */
  1147. X            store(ANY);
  1148. X            break;
  1149. X
  1150. X        case '^':               /* match beginning.. */
  1151. X            store(BOL);
  1152. X            break;
  1153. X
  1154. X        case '$':               /* match endofline.. */
  1155. X            store(EOL);
  1156. X            break;
  1157. X
  1158. X        case '[':               /* match char class..*/
  1159. X            store(CCL);
  1160. X
  1161. X            if (*++p == '^') {
  1162. X                mask = 0377;    
  1163. X                p++;
  1164. X            }
  1165. X            else
  1166. X                mask = 0;
  1167. X
  1168. X            if (*p == '-')        /* real dash */
  1169. X                chset(*p++);
  1170. X            if (*p == ']')        /* real brac */
  1171. X                chset(*p++);
  1172. X            while (*p && *p != ']') {
  1173. X                if (*p == '-' && *(p+1) && *(p+1) != ']') {
  1174. X                    p++;
  1175. X                    c1 = *(p-2) + 1;
  1176. X                    c2 = *p++;
  1177. X                    while (c1 <= c2) {
  1178. X                        if(isalpha(c1) && ignoreCase) {
  1179. X                            chset(toupper(c1));
  1180. X                            chset(tolower(c1));
  1181. X                        } else
  1182. X                            chset(c1);
  1183. X                        ++c1;
  1184. X                    }
  1185. X                }
  1186. X#ifdef EXTEND
  1187. X                else if (*p == '\\' && *(p+1)) {
  1188. X                    p++;
  1189. X                    chset(*p++);
  1190. X                }
  1191. X#endif
  1192. X                else {
  1193. X                    ch = *p++;
  1194. X                    if( isalpha(ch) && ignoreCase ) {
  1195. X                        chset(toupper(ch));
  1196. X                        chset(tolower(ch));
  1197. X                    } else
  1198. X                        chset(ch);
  1199. X                }
  1200. X            }
  1201. X            if (!*p)
  1202. X                badpat("Missing ]");
  1203. X
  1204. X            for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
  1205. X                store(mask ^ bittab[n]);
  1206. X    
  1207. X            break;
  1208. X
  1209. X        case '*':               /* match 0 or more.. */
  1210. X        case '+':               /* match 1 or more.. */
  1211. X            if (p == pat)
  1212. X                badpat("Empty closure");
  1213. X            lp = sp;        /* previous opcode */
  1214. X            if (*lp == CLO)        /* equivalence..   */
  1215. X                break;
  1216. X            switch(*lp) {
  1217. X
  1218. X            case BOL:
  1219. X            case BOT:
  1220. X            case EOT:
  1221. X            case BOW:
  1222. X            case EOW:
  1223. X            case REF:
  1224. X                badpat("Illegal closure");
  1225. X            default:
  1226. X                break;
  1227. X            }
  1228. X
  1229. X            if (*p == '+')
  1230. X                for (sp = mp; lp < sp; lp++)
  1231. X                    store(*lp);
  1232. X
  1233. X            store(END);
  1234. X            store(END);
  1235. X            sp = mp;
  1236. X            while (--mp > lp)
  1237. X                *mp = mp[-1];
  1238. X            store(CLO);
  1239. X            mp = sp;
  1240. X            break;
  1241. X
  1242. X        case '\\':              /* tags, backrefs .. */
  1243. X            switch(*++p) {
  1244. X
  1245. X            case '(':
  1246. X                if (tagc < MAXTAG) {
  1247. X                    tagstk[++tagi] = tagc;
  1248. X                    store(BOT);
  1249. X                    store(tagc++);
  1250. X                }
  1251. X                else
  1252. X                    badpat("Too many \\(\\) pairs");
  1253. X                break;
  1254. X            case ')':
  1255. X                if (*sp == BOT)
  1256. X                    badpat("Null pattern inside \\(\\)");
  1257. X                if (tagi > 0) {
  1258. X                    store(EOT);
  1259. X                    store(tagstk[tagi--]);
  1260. X                }
  1261. X                else
  1262. X                    badpat("Unmatched \\)");
  1263. X                break;
  1264. X            case '<':
  1265. X                store(BOW);
  1266. X                break;
  1267. X            case '>':
  1268. X                if (*sp == BOW)
  1269. X                    badpat("Null pattern inside \\<\\>");
  1270. X                store(EOW);
  1271. X                break;
  1272. X            case '1':
  1273. X            case '2':
  1274. X            case '3':
  1275. X            case '4':
  1276. X            case '5':
  1277. X            case '6':
  1278. X            case '7':
  1279. X            case '8':
  1280. X            case '9':
  1281. X                n = *p-'0';
  1282. X                if (tagi > 0 && tagstk[tagi] == n)
  1283. X                    badpat("Cyclical reference");
  1284. X                if (tagc > n) {
  1285. X                    store(REF);
  1286. X                    store(n);
  1287. X                }
  1288. X                else
  1289. X                    badpat("Undetermined reference");
  1290. X                break;
  1291. X            case 'b':
  1292. X                store(CHR);
  1293. X                store('\b');
  1294. X                break;
  1295. X            case 'n':
  1296. X                store(CHR);
  1297. X                store('\n');
  1298. X                break;
  1299. X            case 'f':
  1300. X                store(CHR);
  1301. X                store('\f');
  1302. X                break;
  1303. X            case 'r':
  1304. X                store(CHR);
  1305. X                store('\r');
  1306. X                break;
  1307. X            case 't':
  1308. X                store(CHR);
  1309. X                store('\t');
  1310. X                break;
  1311. X            default:
  1312. X                store(CHR);
  1313. X                store(*p);
  1314. X            }
  1315. X            break;
  1316. X
  1317. X        default :               /* an ordinary char  */
  1318. X            ch = *p;
  1319. X            if( isalpha(ch) && ignoreCase ) {
  1320. X                store(CHR2);
  1321. X                store(toupper(ch));
  1322. X                store(tolower(ch));
  1323. X            } else {
  1324. X                store(CHR);
  1325. X                store(ch);
  1326. X            }
  1327. X            break;
  1328. X        }
  1329. X        sp = lp;
  1330. X    }
  1331. X    if (tagi > 0)
  1332. X        badpat("Unmatched \\(");
  1333. X    store(END);
  1334. X    sta = OKP;
  1335. X    return 0;
  1336. X}
  1337. X
  1338. static char * bol;
  1339. int regex_bopat[MAXTAG];
  1340. int regex_eopat[MAXTAG];
  1341. int regex_pmatch();
  1342. X
  1343. static int line_count;
  1344. X
  1345. X/*
  1346. X * re_exec:
  1347. X *     execute nfa to find a match.
  1348. X *
  1349. X *    special cases: (nfa[0])    
  1350. X *        BOL
  1351. X *            Match only once, starting from the
  1352. X *            beginning.
  1353. X *        CHR
  1354. X *            First locate the character without
  1355. X *            calling pmatch, and if found, call
  1356. X *            pmatch for the remaining string.
  1357. X *        END
  1358. X *            re_comp failed, poor luser did not
  1359. X *            check for it. Fail fast.
  1360. X *
  1361. X *    If a match is found, regex_bopat[0] and regex_eopat[0] are set
  1362. X *    to the beginning and the end of the matched fragment,
  1363. X *    respectively.
  1364. X *
  1365. X */
  1366. static void
  1367. re_exec_init()
  1368. X{
  1369. X    line_count = 0;
  1370. X
  1371. X    regex_bopat[0] = 0;
  1372. X    regex_bopat[1] = 0;
  1373. X    regex_bopat[2] = 0;
  1374. X    regex_bopat[3] = 0;
  1375. X    regex_bopat[4] = 0;
  1376. X    regex_bopat[5] = 0;
  1377. X    regex_bopat[6] = 0;
  1378. X    regex_bopat[7] = 0;
  1379. X    regex_bopat[8] = 0;
  1380. X    regex_bopat[9] = 0;
  1381. X    
  1382. X    ClearByteCache();
  1383. X}
  1384. X
  1385. int
  1386. re_exec( fid, cp, end_cp, lines_passed)
  1387. X    int fid;
  1388. X    register int cp;
  1389. X    int end_cp;
  1390. X    int *lines_passed;
  1391. X{
  1392. X    char c, c2;
  1393. X    int ep = 0;
  1394. X    CHAR *ap = nfa;
  1395. X    char ch;
  1396. X
  1397. X    re_exec_init();
  1398. X
  1399. X    switch(*ap) {
  1400. X
  1401. X    case CHR2:            /* ordinary char: locate it fast */
  1402. X        c = *(ap+1);
  1403. X        c2 = *(ap+2);
  1404. X        ch = getCachedFileByte( fid, cp );
  1405. X        if( ch == '\n' )
  1406. X            ++line_count;
  1407. X        while( (cp<=end_cp) && (ch != c) && (ch != c2) ) {
  1408. X            ch = getCachedFileByte( fid, ++cp );
  1409. X            if( ch == '\n' )
  1410. X                ++line_count;
  1411. X        }
  1412. X        if( cp > end_cp )    /* if EOS, fail, else fall thru. */
  1413. X            return 0;
  1414. X        goto normalCase;
  1415. X
  1416. X    case CHR:            /* ordinary char: locate it fast */
  1417. X        c = *(ap+1);
  1418. X        ch = getCachedFileByte( fid, cp );
  1419. X        if( ch == '\n' )
  1420. X            ++line_count;
  1421. X        while( (cp<=end_cp) && (ch != c) ) {
  1422. X            ch = getCachedFileByte( fid, ++cp );
  1423. X            if( ch == '\n' )
  1424. X                ++line_count;
  1425. X        }
  1426. X        if( cp > end_cp )    /* if EOS, fail, else fall thru. */
  1427. X            return 0;
  1428. X    default:            /* regular matching all the way. */
  1429. X    normalCase:
  1430. X        while( cp<=end_cp ) {
  1431. X            /*SUPPRESS 560*/
  1432. X            if ((ep = pmatch(fid,cp,end_cp,ap)))
  1433. X                break;
  1434. X            ++cp;
  1435. X        }
  1436. X        break;
  1437. X    case END:            /* munged automaton. fail always */
  1438. X        return 0;
  1439. X    }
  1440. X    if (!ep)
  1441. X        return 0;
  1442. X
  1443. X    if (internal_error)
  1444. X        return -1;
  1445. X
  1446. X    regex_bopat[0] = cp;
  1447. X    regex_eopat[0] = ep;
  1448. X    *lines_passed = line_count;
  1449. X    return 1;
  1450. X}
  1451. X
  1452. int
  1453. re_exec_reversed( fid, cp, end_cp, lines_passed)
  1454. X    int fid;
  1455. X    register int cp;
  1456. X    int end_cp;
  1457. X    int *lines_passed;
  1458. X{
  1459. X    char c, c2;
  1460. X    int ep = 0;
  1461. X    CHAR *ap = nfa;
  1462. X    char ch;
  1463. X    int end_file = fileSize(fid) - 1;
  1464. X
  1465. X    re_exec_init();
  1466. X
  1467. X    switch(*ap) {
  1468. X
  1469. X    case CHR2:            /* ordinary char: locate it fast */
  1470. X        c = *(ap+1);
  1471. X        c2 = *(ap+2);
  1472. X        ch = getCachedFileByte( fid, end_cp );
  1473. X        if( ch == '\n' )
  1474. X            ++line_count;
  1475. X        while( (cp<=end_cp) && (ch != c) && (ch != c2) ) {
  1476. X            ch = getCachedFileByte( fid, --end_cp );
  1477. X            if( ch == '\n' )
  1478. X                ++line_count;
  1479. X        }
  1480. X        if( cp > end_cp )    /* if EOS, fail, else fall thru. */
  1481. X            return 0;
  1482. X        goto normalCase;
  1483. X
  1484. X    case CHR:            /* ordinary char: locate it fast */
  1485. X        c = *(ap+1);
  1486. X        ch = getCachedFileByte( fid, end_cp );
  1487. X        if( ch == '\n' )
  1488. X            ++line_count;
  1489. X        while( (cp<=end_cp) && (ch != c) ) {
  1490. X            ch = getCachedFileByte( fid, --end_cp );
  1491. X            if( ch == '\n' )
  1492. X                ++line_count;
  1493. X        }
  1494. X        if( cp > end_cp )    /* if EOS, fail, else fall thru. */
  1495. X            return 0;
  1496. X    default:            /* regular matching all the way. */
  1497. X    normalCase:
  1498. X        while( cp<=end_cp ) {
  1499. X            /*SUPPRESS 560*/
  1500. X            if ((ep = pmatch(fid,end_cp,end_file,ap)))
  1501. X                break;
  1502. X            --end_cp;
  1503. X        }
  1504. X        break;
  1505. X    case END:            /* munged automaton. fail always */
  1506. X        return 0;
  1507. X    }
  1508. X    if (!ep)
  1509. X        return 0;
  1510. X
  1511. X    if (internal_error)
  1512. X        return -1;
  1513. X
  1514. X    regex_bopat[0] = end_cp;
  1515. X    regex_eopat[0] = ep;
  1516. X    *lines_passed = line_count;
  1517. X    return 1;
  1518. X}
  1519. X
  1520. X
  1521. X/* 
  1522. X * pmatch: 
  1523. X *    internal routine for the hard part
  1524. X *
  1525. X *     This code is mostly snarfed from an early
  1526. X *     grep written by David Conroy. The backref and
  1527. X *     tag stuff, and various other mods are by oZ.
  1528. X *
  1529. X *    special cases: (nfa[n], nfa[n+1])
  1530. X *        CLO ANY
  1531. X *            We KNOW ".*" will match ANYTHING
  1532. X *            upto the end of line. Thus, go to
  1533. X *            the end of line straight, without
  1534. X *            calling pmatch recursively. As in
  1535. X *            the other closure cases, the remaining
  1536. X *            pattern must be matched by moving
  1537. X *            backwards on the string recursively,
  1538. X *            to find a match for xy (x is ".*" and 
  1539. X *            y is the remaining pattern) where
  1540. X *            the match satisfies the LONGEST match
  1541. X *            for x followed by a match for y.
  1542. X *        CLO CHR
  1543. X *            We can again scan the string forward
  1544. X *            for the single char without recursion, 
  1545. X *            and at the point of failure, we execute 
  1546. X *            the remaining nfa recursively, as
  1547. X *            described above.
  1548. X *
  1549. X *    At the end of a successful match, regex_bopat[n] and regex_eopat[n]
  1550. X *    are set to the beginning and end of subpatterns matched
  1551. X *    by tagged expressions (n = 1 to 9).    
  1552. X *
  1553. X */
  1554. X
  1555. X/*
  1556. X * character classification table for word boundary
  1557. X * operators BOW and EOW. the reason for not using 
  1558. X * ctype macros is that we can let the user add into 
  1559. X * our own table. see re_modw. This table is not in
  1560. X * the bitset form, since we may wish to extend it
  1561. X * in the future for other character classifications. 
  1562. X *
  1563. X *    TRUE for 0-9 A-Z a-z _
  1564. X */
  1565. static char chrtyp[MAXCHR] = {
  1566. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  1567. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  1568. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  1569. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  1570. X    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
  1571. X    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 
  1572. X    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
  1573. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1574. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1575. X    1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 
  1576. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1577. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1578. X    1, 1, 1, 0, 0, 0, 0, 0
  1579. X    };
  1580. X
  1581. X#define inascii(x)    (0177&(x))
  1582. X#define iswordc(x)     chrtyp[inascii(x)]
  1583. X#define isinset(x,y)     ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
  1584. X
  1585. X/*
  1586. X * skip values for CLO XXX to skip past the closure
  1587. X *
  1588. X */
  1589. X
  1590. X#define ANYSKIP    2     /* [CLO] ANY END ...         */
  1591. X#define CHRSKIP    3    /* [CLO] CHR chr END ...     */
  1592. X#define CHR2SKIP 4    /* [CLO] CHR chr END ...     */
  1593. X#define CCLSKIP 18    /* [CLO] CCL 16bytes END ... */
  1594. X
  1595. static int
  1596. pmatch( fid, cp, end_cp, ap )
  1597. X    int fid;
  1598. X    register int cp;
  1599. X    register int end_cp;
  1600. X    register CHAR *ap;
  1601. X{
  1602. X    register int op, c, n;
  1603. X    register int e;        /* extra pointer for CLO */
  1604. X    register int bp;        /* beginning of subpat.. */
  1605. X    register int ep;        /* ending of subpat..     */
  1606. X    int are;            /* to save the line ptr. */
  1607. X    char ch, c2;
  1608. X
  1609. X    while ((op = *ap++) != END) {
  1610. X        ch = getCachedFileByte( fid, cp );
  1611. X        if( ch == '\n' )
  1612. X            ++line_count;
  1613. X        switch(op) {
  1614. X
  1615. X        case CHR:
  1616. X            ++cp;
  1617. X            if( ch != *ap++ )
  1618. X                return 0;
  1619. X            break;
  1620. X        case CHR2:
  1621. X            ++cp;
  1622. X            /* first check against the upper case letter */
  1623. X            if( ch != *ap++ ) {
  1624. X                /* check against the lower case letter */
  1625. X                if( ch != *ap++ )
  1626. X                    /* if neither, then no match */
  1627. X                    return 0;
  1628. X            } else
  1629. X                ++ap; /* skip the lower case character */
  1630. X            break;
  1631. X        case ANY:
  1632. X            ++cp;
  1633. X            /* the ANY wildcard does not match newlines */
  1634. X            if( (ch == '\n') || (cp > end_cp) )
  1635. X                return 0;
  1636. X            break;
  1637. X        case CCL:
  1638. X            ++cp;
  1639. X            if( !isinset(ap,ch) )
  1640. X                return 0;
  1641. X            ap += BITBLK;
  1642. X            break;
  1643. X        case BOL:
  1644. X            if( cp > 0 && '\n' != getCachedFileByte(fid,cp-1) )
  1645. X                return 0;
  1646. X            break;
  1647. X        case EOL:
  1648. X            if( getCachedFileByte(fid,cp+1) != '\n' )
  1649. X                return 0;
  1650. X            break;
  1651. X        case BOT:
  1652. X            regex_bopat[*ap++] = cp;
  1653. X            break;
  1654. X        case EOT:
  1655. X            regex_eopat[*ap++] = cp;
  1656. X            break;
  1657. X         case BOW:
  1658. X            if(
  1659. X                (cp > 0 && iswordc( getCachedFileByte(fid,cp-1) ))
  1660. X                || !iswordc(ch)
  1661. X             )
  1662. X                return 0;
  1663. X            break;
  1664. X        case EOW:
  1665. X            if( !iswordc(getCachedFileByte(fid,cp-1)) || iswordc(ch) )
  1666. X                return 0;
  1667. X            break;
  1668. X        case REF:
  1669. X            n = *ap++;
  1670. X            bp = regex_bopat[n];
  1671. X            ep = regex_eopat[n];
  1672. X            while( bp < ep ) {
  1673. X                if( getCachedFileByte(fid,bp++)
  1674. X                        != getCachedFileByte(fid,cp++) )
  1675. X                    return 0;
  1676. X            }
  1677. X            break;
  1678. X        case CLO:
  1679. X/************************************
  1680. Handle line counts in closures correctly
  1681. X***************************************/
  1682. X            are = cp;
  1683. X            switch( *ap ) {
  1684. X
  1685. X            case ANY:
  1686. X                /* the ANY wildcard does not match newlines */
  1687. X                while( (ch != '\n') && (cp <= end_cp) )
  1688. X                    ch = getCachedFileByte( fid, ++cp );
  1689. X                n = ANYSKIP;
  1690. X                break;
  1691. X            case CHR:
  1692. X                c = *(ap+1);
  1693. X                while( (cp<=end_cp) && c == ch )
  1694. X                    ch = getCachedFileByte( fid, ++cp );
  1695. X                n = CHRSKIP;
  1696. X                break;
  1697. X            case CHR2:
  1698. X                c = *(ap+1);
  1699. X                c2 = *(ap+2);
  1700. X                while( (cp<=end_cp) && (c == ch || c2 == ch) )
  1701. X                    ch = getCachedFileByte( fid, ++cp );
  1702. X                n = CHR2SKIP;
  1703. X                break;
  1704. X            case CCL:
  1705. X                while( (cp <= end_cp) && isinset(ap+1,ch) )
  1706. X                    ch = getCachedFileByte( fid, ++cp );
  1707. X                n = CCLSKIP;
  1708. X                break;
  1709. X            default:
  1710. X                internal_error++;
  1711. X                return 0;
  1712. X            }
  1713. X
  1714. X            ap += n;
  1715. X
  1716. X            while( cp >= are ) {
  1717. X                /*SUPPRESS 560*/
  1718. X                if( e = pmatch(fid,cp,end_cp,ap) )
  1719. X                    return e;
  1720. X                --cp;
  1721. X            }
  1722. X            return 0;
  1723. X        default:
  1724. X            internal_error++;
  1725. X            return 0;
  1726. X        }
  1727. X    }
  1728. X    return cp;
  1729. X}
  1730. X
  1731. char * pmatch2();
  1732. X
  1733. int
  1734. re_match( lp )
  1735. X    CHAR *lp;
  1736. X{
  1737. X    char * ep;
  1738. X    
  1739. X    bol = lp;
  1740. X
  1741. X    ep = pmatch2( lp, nfa );
  1742. X
  1743. X    if( ep == 0 )
  1744. X        return 0;
  1745. X    else
  1746. X        return 1;
  1747. X}
  1748. X
  1749. static char *
  1750. pmatch2( lp, ap )
  1751. X    register CHAR *lp;
  1752. X    register CHAR *ap;
  1753. X{
  1754. X    register int op, c, n;
  1755. X    register char * e;        /* extra pointer for CLO */
  1756. X    char * are;            /* to save the line ptr. */
  1757. X
  1758. X    while ((op = *ap++) != END) {
  1759. X        switch(op) {
  1760. X
  1761. X        case CHR:
  1762. X            if( *lp++ != *ap++ )
  1763. X                return 0;
  1764. X            break;
  1765. X        case ANY:
  1766. X            if( !*lp++ )
  1767. X                return 0;
  1768. X            break;
  1769. X        case CCL:
  1770. X            c = *lp++;
  1771. X            if( !isinset(ap,c) )
  1772. X                return 0;
  1773. X            ap += BITBLK;
  1774. X            break;
  1775. X        case BOL:
  1776. X            if( lp != bol )
  1777. X                return 0;
  1778. X            break;
  1779. X        case EOL:
  1780. X            if( *lp )
  1781. X                return 0;
  1782. X            break;
  1783. X        case CLO:
  1784. X            are = lp;
  1785. X            switch( *ap ) {
  1786. X
  1787. X            case ANY:
  1788. X                while( *lp )
  1789. X                    lp++;
  1790. X                n = ANYSKIP;
  1791. X                break;
  1792. X            case CHR:
  1793. X                c = *(ap+1);
  1794. X                while( *lp && c == *lp )
  1795. X                    lp++;
  1796. X                n = CHRSKIP;
  1797. X                break;
  1798. X            case CCL:
  1799. X                while( (c = *lp) && isinset(ap+1,c) )
  1800. X                    lp++;
  1801. X                n = CCLSKIP;
  1802. X                break;
  1803. X            default:
  1804. X                internal_error++;
  1805. X                return 0;
  1806. X            }
  1807. X
  1808. X            ap += n;
  1809. X
  1810. X            while( lp >= are ) {
  1811. X                /*SUPPRESS 560*/
  1812. X                if( e = pmatch2( lp, ap ) )
  1813. X                    return e;
  1814. X                --lp;
  1815. X            }
  1816. X            return 0;
  1817. X        default:
  1818. X            internal_error++;
  1819. X            return 0;
  1820. X        }
  1821. X    }
  1822. X    return lp;
  1823. X}
  1824. X
  1825. X/*ARGSUSED*/
  1826. void
  1827. RegexReplaceAll( w, searchFor, replaceWith, inSelection )
  1828. X    struct window * w;
  1829. X    char * searchFor;
  1830. X    char * replaceWith;
  1831. X    int inSelection;
  1832. X{
  1833. X    printf("RegexReplaceAll: not implemented yet\n");
  1834. X}
  1835. X
  1836. X#define BUFFER_LENGTH    1024
  1837. X
  1838. X/*ARGSUSED*/
  1839. int
  1840. RegexReplaceOne( w, searchFor, replaceWith )
  1841. X    struct window * w;
  1842. X    char * searchFor;
  1843. X    char * replaceWith;
  1844. X{
  1845. X    extern Offset selBegin, selEnd;
  1846. X    extern char msgBuffer[];
  1847. X    extern struct window *selWindow;
  1848. X
  1849. X    int cp, cp_limit, diff_lengths;
  1850. X    char buffer[BUFFER_LENGTH];
  1851. X    char * to = buffer;
  1852. X    char * to_limit = to + BUFFER_LENGTH;
  1853. X    char * from = replaceWith;
  1854. X
  1855. X    while( *from != '\0' ) {
  1856. X        char ch = *from++;
  1857. X        switch( ch ) {
  1858. X        default:
  1859. X            *to++ = ch;
  1860. X            break;
  1861. X        case '&':
  1862. X            cp = regex_bopat[0];
  1863. X            cp_limit = regex_eopat[0];
  1864. X            while( cp < cp_limit ) {
  1865. X                *to++ = getFileByte(w->fileId, cp++);
  1866. X                if( to >= to_limit )
  1867. X                    --to;
  1868. X            }
  1869. X            break;
  1870. X        case '\\':
  1871. X            ch = *from++;
  1872. X            switch( ch ) {
  1873. X            default:
  1874. X                *to++ = ch;
  1875. X                break;
  1876. X            case '\\':
  1877. X                *to++ = '\\';
  1878. X                break;
  1879. X            case '1': case '2': case '3': case '4': case '5':
  1880. X            case '6': case '7': case '8': case '9': 
  1881. X                cp = regex_bopat[ch-'0'];
  1882. X                cp_limit = regex_eopat[ch-'0'];
  1883. X                while( cp < cp_limit ) {
  1884. X                    *to++ = getFileByte(w->fileId, cp++);
  1885. X                    if( to >= to_limit )
  1886. X                        --to;
  1887. X                }
  1888. X                break;
  1889. X            }
  1890. X        }
  1891. X        if( to >= to_limit )
  1892. X            --to;
  1893. X    }
  1894. X    *to = '\0';
  1895. X    selBegin = regex_bopat[0];
  1896. X    selEnd = regex_eopat[0] - 1;
  1897. X    diff_lengths = strlen(buffer) - (selEnd-selBegin);
  1898. X    if( selBegin <= selEnd )
  1899. X        deleteChars( w->fileId, UPDATEWINDOWS, 1 );
  1900. X    else
  1901. X        selEnd = selBegin;
  1902. X    for( from = buffer; *from != '\0'; ++from )
  1903. X        insertChar( *from );
  1904. X    drawWindow( selWindow );
  1905. X    return diff_lengths;
  1906. X}
  1907. X
  1908. END_OF_FILE
  1909. if test 22890 -ne `wc -c <'regex.c'`; then
  1910.     echo shar: \"'regex.c'\" unpacked with wrong size!
  1911. fi
  1912. # end of 'regex.c'
  1913. fi
  1914. echo shar: End of archive 8 \(of 15\).
  1915. cp /dev/null ark8isdone
  1916. MISSING=""
  1917. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1918.     if test ! -f ark${I}isdone ; then
  1919.     MISSING="${MISSING} ${I}"
  1920.     fi
  1921. done
  1922. if test "${MISSING}" = "" ; then
  1923.     echo You have unpacked all 15 archives.
  1924.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1925. else
  1926.     echo You still need to unpack the following archives:
  1927.     echo "        " ${MISSING}
  1928. fi
  1929. ##  End of shell archive.
  1930. exit 0
  1931. -- 
  1932. --
  1933. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1934. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1935. Sunnyvale, California 94086            at&t: 408/522-9236
  1936.