home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2959 < prev    next >
Encoding:
Internet Message Format  |  1991-03-04  |  47.7 KB

  1. From: lee@sq.sq.com (Liam R. E. Quin)
  2. Newsgroups: alt.sources
  3. Subject: lq-text Full Text Retrieval Database Part 11/13
  4. Message-ID: <1991Mar4.021055.16938@sq.sq.com>
  5. Date: 4 Mar 91 02:10:55 GMT
  6.  
  7. : cut here --- cut here --
  8. : To unbundle, sh this file
  9. #! /bin/sh
  10. : part 11
  11. echo x - lq-text/src/test/trywid.c 1>&2
  12. sed 's/^X//' >lq-text/src/test/trywid.c <<'@@@End of lq-text/src/test/trywid.c'
  13. X/* trywid.c -- Copyright 1989 Liam R. Quin.  All Rights Reserved.
  14. X * This code is NOT in the public domain.
  15. X * See the file COPYRIGHT for full details.
  16. X *
  17. X * $Header: /usr/src/cmd/lq-text/src/test/RCS/trywid.c,v 1.1 90/08/09 19:17:51 lee Rel1-10 $
  18. X *
  19. X * $Log:    trywid.c,v $
  20. X * Revision 1.1  90/08/09  19:17:51  lee
  21. X * Initial revision
  22. X * 
  23. X *
  24. X */
  25. X
  26. X#include "globals.h" /* defines and declarations for database filenames */
  27. X
  28. X#include <sys/types.h>
  29. X#include <stdio.h>
  30. X#include "fileinfo.h"
  31. X#include "wordinfo.h"
  32. X
  33. X/** Unix Library Functions: **/
  34. Xextern long atol();
  35. X/** liblqtext functions: **/
  36. Xextern t_WID GetMaxWID();
  37. Xextern t_WID GetNextWID();
  38. X/** **/
  39. X
  40. Xint
  41. Xmain(argc, argv)
  42. X    int argc;
  43. X    char *argv[];
  44. X{
  45. X    t_WID W, Max;
  46. X
  47. X    Max = atol(argv[1]);
  48. X
  49. X    for (W = GetMaxWID(); W <= Max; ) {
  50. X    printf("%lu\n", W = GetNextWID());
  51. X    }
  52. X    return 0;
  53. X}
  54. @@@End of lq-text/src/test/trywid.c
  55. echo x - lq-text/src/test/wordlengths 1>&2
  56. sed 's/^X//' >lq-text/src/test/wordlengths <<'@@@End of lq-text/src/test/wordlengths'
  57. XA
  58. XBB
  59. XCCC
  60. XDDDD
  61. XEEEEE
  62. XFFFFFF
  63. XGGGGGGG
  64. XHHHHHHHH
  65. XIIIIIIIII
  66. XJJJJJJJJJJ
  67. XKKKKKKKKKKK
  68. XLLLLLLLLLLLL
  69. XMMMMMMMMMMMMM
  70. XNNNNNNNNNNNNNN
  71. XOOOOOOOOOOOOOOO
  72. XPPPPPPPPPPPPPPPP
  73. XQQQQQQQQQQQQQQQQQ
  74. XRRRRRRRRRRRRRRRRRR
  75. XSSSSSSSSSSSSSSSSSSS
  76. XTTTTTTTTTTTTTTTTTTTT
  77. XUUUUUUUUUUUUUUUUUUUUU
  78. XVVVVVVVVVVVVVVVVVVVVVV
  79. XWWWWWWWWWWWWWWWWWWWWWWW
  80. XXXXXXXXXXXXXXXXXXXXXXXXX
  81. XYYYYYYYYYYYYYYYYYYYYYYYYY
  82. XZZZZZZZZZZZZZZZZZZZZZZZZZZ
  83. X
  84. XA
  85. XBB
  86. XCCC
  87. XDDDD
  88. XEEEEE
  89. XFFFFFF
  90. XGGGGGGG
  91. XHHHHHHHH
  92. XIIIIIIIII
  93. XJJJJJJJJJJ
  94. XKKKKKKKKKKK
  95. XLLLLLLLLLLLL
  96. XMMMMMMMMMMMMM
  97. XNNNNNNNNNNNNNN
  98. XOOOOOOOOOOOOOOO
  99. XPPPPPPPPPPPPPPPP
  100. XQQQQQQQQQQQQQQQQQ
  101. XRRRRRRRRRRRRRRRRRR
  102. XSSSSSSSSSSSSSSSSSSS
  103. XTTTTTTTTTTTTTTTTTTTT
  104. XUUUUUUUUUUUUUUUUUUUUU
  105. XVVVVVVVVVVVVVVVVVVVVVV
  106. XWWWWWWWWWWWWWWWWWWWWWWW
  107. XXXXXXXXXXXXXXXXXXXXXXXXX
  108. XYYYYYYYYYYYYYYYYYYYYYYYYY
  109. XZZZZZZZZZZZZZZZZZZZZZZZZZZ
  110. X
  111. @@@End of lq-text/src/test/wordlengths
  112. echo x - lq-text/src/ozmahash/Makefile 1>&2
  113. sed 's/^X//' >lq-text/src/ozmahash/Makefile <<'@@@End of lq-text/src/ozmahash/Makefile'
  114. X# $Id: Makefile,v 1.2 91/03/02 19:10:36 lee Exp $
  115. XDIR=    .
  116. XSRC1=    dynahash.c log2.c page.c big.c buf.c hfunc.c
  117. XSRC2=    mkstemp.c bcopy.c 
  118. XSRCS=    $(SRC1) $(SRC2)
  119. X#SRCS=    $(SRC1) 
  120. XOBJ1=    dynahash.o log2.o page.o big.o buf.o hfunc.o
  121. XOBJ2=    mkstemp.o bcopy.o 
  122. XOBJS=    $(OBJ1) $(OBJ2)
  123. X#OBJS=    $(OBJ1) 
  124. XMAIN1=    tread2.c tverify.c tseq.c tdel.c thash4.c tcreat3.c 
  125. XMAINS=    thash.c tcreat.c tread.c tread2.c tverify.c tseq.c tseq2.c tcreat2.c thash2.c tdel.c thash3.c thash4.c tcreat3.c 
  126. XHDRS=    hash.h page.h db.h endian.h
  127. XRANLIB=ranlib
  128. X
  129. XDEBUGFLAGS= -DHASH_STATISTICS -g -pg
  130. XPROFFLAGS= -p -DHASH_STATISTICS
  131. XTIMEFLAGS = -O2
  132. XTESTFLAGS= $(DEBUGFLAGS) 
  133. XLDFLAGS= 
  134. X#CFLAGS=    -I.  $(DEBUGFLAGS)
  135. X#CFLAGS=    -I.  $(PROFFLAGS)
  136. XCFLAGS=    -I.  $(TIMEFLAGS)
  137. X
  138. Xall: install
  139. X    $(MAKE) -$(MAKEFLAGS) tidy
  140. X
  141. X#all:    libhash.a tread2 tverify tseq thash4 tcreat3 tdel
  142. X#all:    tcreat tread tread2 tverify thash tseq tseq2 tcreat2 thash2 thash3 thash4 tdel tcreat3
  143. X
  144. Xlib:    libhash.a
  145. X
  146. Xinstall: lib
  147. X    cp libhash.a ../lib
  148. X    $(RANLIB) ../lib/libhash.a
  149. X
  150. Xtidy:
  151. X    /bin/rm -f *.o core *.out
  152. X
  153. Xclean: tidy
  154. X    /bin/rm -f core *.a
  155. X
  156. Xtar:    
  157. X    tar cf hash.tar README Makefile $(SRCS) $(MAIN1) $(HDRS) ndbm.c ndbm.h hsearch.c search.h byte_order.c db.3 hash.ps
  158. X
  159. Xshar:    
  160. X    shar -f XFER $(SRC1) $(MAINS) $(HDRS) Makefile
  161. X
  162. Xlibhash.a:    $(OBJS) ndbm.o hsearch.o
  163. X    ar ruv libhash.a $(OBJS) ndbm.o hsearch.o
  164. X    $(RANLIB) libhash.a
  165. X
  166. Xtdel:    tdel.o $(OBJS)
  167. X    cc tdel.o $(LDFLAGS) -o tdel $(OBJS)
  168. X
  169. Xtseq2:    tseq2.o $(OBJS)
  170. X    cc tseq2.o $(LDFLAGS) -o tseq2 $(OBJS)
  171. X
  172. Xtseq:    tseq.o $(OBJS)
  173. X    cc tseq.o $(LDFLAGS) -o tseq $(OBJS)
  174. X
  175. Xtverify:    tverify.o $(OBJS)
  176. X    cc tverify.o $(LDFLAGS) -o tverify $(OBJS)
  177. X
  178. Xtcreat2:    tcreat2.o $(OBJS)
  179. X    cc tcreat2.o $(LDFLAGS) -o tcreat2 $(OBJS)
  180. X
  181. Xtcreat3:    tcreat3.o $(OBJS)
  182. X    cc tcreat3.o $(LDFLAGS) -o tcreat3 $(OBJS)
  183. X
  184. Xtcreat:    tcreat.o $(OBJS)
  185. X    cc tcreat.o $(LDFLAGS) -o tcreat $(OBJS)
  186. X
  187. Xtread:    tread.o $(OBJS)
  188. X    cc tread.o $(LDFLAGS) -o tread $(OBJS)
  189. X
  190. Xtread2:    tread2.o $(OBJS)
  191. X    cc tread2.o $(LDFLAGS) -o tread2 $(OBJS)
  192. X
  193. Xthash:    thash.o $(OBJS)
  194. X    cc thash.o $(LDFLAGS) -o thash $(OBJS)
  195. X
  196. Xthash2:    thash2.o $(OBJS)
  197. X    cc thash2.o $(LDFLAGS) -o thash2 $(OBJS)
  198. X
  199. Xthash3:    thash3.o $(OBJS)
  200. X    cc thash3.o $(LDFLAGS) -o thash3 $(OBJS)
  201. X
  202. Xthash4:    thash4.o $(OBJS)
  203. X    cc thash4.o $(LDFLAGS) -o thash4 $(OBJS)
  204. X
  205. X
  206. Xsrc:    
  207. X    co $(SRCS) $(HDRS) $(MAINS)
  208. X
  209. Xdepend:
  210. X    mkdep $(CFLAGS) $(SRCS)
  211. X
  212. X# DO NOT DELETE THIS LINE -- mkdep uses it.
  213. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
  214. X
  215. Xdynahash.o: dynahash.c db.h hash.h  endian.h
  216. Xlog2.o: log2.c
  217. Xpage.o: page.c db.h hash.h page.h  endian.h
  218. Xbig.o: big.c db.h hash.h page.h 
  219. Xbuf.o: buf.c hash.h 
  220. Xhfunc.o: hfunc.c
  221. Xmkstemp.o: mkstemp.c  
  222. Xbcopy.o: bcopy.c  
  223. X
  224. X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
  225. @@@End of lq-text/src/ozmahash/Makefile
  226. echo x - lq-text/src/ozmahash/README 1>&2
  227. sed 's/^X//' >lq-text/src/ozmahash/README <<'@@@End of lq-text/src/ozmahash/README'
  228. XThis package implements a superset of the hsearch and dbm/ndbm libraries.
  229. X
  230. XContents:
  231. X
  232. XHashing Package:
  233. X    dynahash.c
  234. X    page.c
  235. X    buf.c
  236. X    big.c
  237. X    hfunc.c
  238. X    log2.c
  239. X
  240. X    hash.h
  241. X    page.h
  242. X    db.h
  243. X
  244. XBackward Compatibility Routines:
  245. X    ndbm.c
  246. X    ndbm.h
  247. X    hsearch.c
  248. X    search.h
  249. X
  250. XMisc
  251. X    byte_order.c
  252. X
  253. XBSD Files:
  254. X    endian.h
  255. X    mkstemp.c
  256. X    bcopy.c
  257. X
  258. XTest Programs:
  259. X    All test programs which need key/data pairs expect them entered
  260. X    with key and data on separate lines
  261. X
  262. X    tcreat3.c    
  263. X        Takes 
  264. X            bucketsize (bsize), 
  265. X            fill factor (ffactor), and
  266. X            initial number of elements (nelem).  
  267. X        Creates a hash table named hashtest containing the 
  268. X        keys/data pairs entered from standard in.
  269. X    thash4.c
  270. X        Takes
  271. X            bucketsize (bsize), 
  272. X            fill factor (ffactor), 
  273. X            initial number of elements (nelem)
  274. X            bytes of cache (ncached), and
  275. X            file from which to read data  (fname)
  276. X        Creates a table from the key/data pairs on standard in and
  277. X        then does a read of each key/data in fname
  278. X    tdel.c
  279. X        Takes
  280. X            bucketsize (bsize), and
  281. X            fill factor (ffactor).
  282. X            file from which to read data (fname)
  283. X        Reads each key/data pair from fname and deletes the
  284. X        key from the hash table hashtest
  285. X    tseq.c
  286. X        Reads the key/data pairs in the file hashtest and writes them
  287. X        to standard out.
  288. X    tread2.c
  289. X        Takes
  290. X            butes of cache (ncached).
  291. X        Reads key/data pairs from standard in and looks them up
  292. X        in the file hashtest.
  293. X    tverify.c
  294. X        Reads key/data pairs from standard in, looks them up
  295. X        in the file hashtest, and verifies that the data is
  296. X        correct.
  297. X
  298. XIf you are running on a BSD system, the BSD h files should be in 
  299. X/usr/include and the BSD .c files should be in libc.  On a non-BSD 
  300. Xsystem, you will need to compile the copies here into the package.  
  301. XBe sure to set BYTE_ORDER in endian.h appropriately for your machine.  
  302. XIf you don't know what "endian" your machine is, compile byte_order.c 
  303. Xand run it.  It should tell you.
  304. X
  305. XThe file search.h is used only for using the hsearch compatible interface on
  306. XBSD systems.  On System V derived systems, search.h should appear in 
  307. X/usr/include.
  308. X
  309. XThe man page db.3 explains the interface to the hashing system.
  310. XThe file hash.ps is a postscript copy of a paper explaining
  311. Xthe history, implementation, and performance of the hash package.
  312. X
  313. X"bugs" or idiosyncracies
  314. X
  315. XIf you have a lot of overflows, it is possible to run out of overflow
  316. Xpages.  Currently, this will cause a message to be printed on stderr.
  317. XEventually, this will be indicated by a return error code.
  318. X
  319. XIf you have a lot of overflow pages and a small cache, you might run
  320. Xout of buffers to hold a single hash chain.  You will get an error
  321. Xexit.  If you have very long keys and/or small pages, try increasing
  322. Xyour buffer pool space to make this go away (you can also compile
  323. Xwith HASH_STATISTICS to see just how many expansions you really are
  324. Xgetting).
  325. @@@End of lq-text/src/ozmahash/README
  326. echo x - lq-text/src/ozmahash/bcopy.c 1>&2
  327. sed 's/^X//' >lq-text/src/ozmahash/bcopy.c <<'@@@End of lq-text/src/ozmahash/bcopy.c'
  328. X/*-
  329. X * Copyright (c) 1990 The Regents of the University of California.
  330. X * All rights reserved.
  331. X *
  332. X * This code is derived from software contributed to Berkeley by
  333. X * Chris Torek.
  334. X *
  335. X * Redistribution and use in source and binary forms are permitted
  336. X * provided that: (1) source distributions retain this entire copyright
  337. X * notice and comment, and (2) distributions including binaries display
  338. X * the following acknowledgement:  ``This product includes software
  339. X * developed by the University of California, Berkeley and its contributors''
  340. X * in the documentation or other materials provided with the distribution
  341. X * and in all advertising materials mentioning features or use of this
  342. X * software. Neither the name of the University nor the names of its
  343. X * contributors may be used to endorse or promote products derived
  344. X * from this software without specific prior written permission.
  345. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  346. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  347. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  348. X */
  349. X
  350. X#if defined(LIBC_SCCS) && !defined(lint)
  351. Xstatic char sccsid[] = "@(#)bcopy.c    5.7 (Berkeley) 5/16/90";
  352. X#endif /* LIBC_SCCS and not lint */
  353. X
  354. X#include <string.h>
  355. X#include <sys/types.h>
  356. X
  357. X/*
  358. X * sizeof(word) MUST BE A POWER OF TWO
  359. X * SO THAT wmask BELOW IS ALL ONES
  360. X */
  361. Xtypedef    int word;        /* "word" used for optimal copy speed */
  362. X
  363. X#define    wsize    sizeof(word)
  364. X#define    wmask    (wsize - 1)
  365. X
  366. X/*
  367. X * Copy a block of memory, handling overlap.
  368. X * This is the routine that actually implements
  369. X * (the portable versions of) bcopy, memcpy, and memmove.
  370. X */
  371. Xvoid
  372. Xbcopy(src0, dst0, length)
  373. X    char *dst0;
  374. X    char *src0;
  375. X    register size_t length;
  376. X{
  377. X    register char *dst = dst0;
  378. X    register char *src = src0;
  379. X    register size_t t;
  380. X
  381. X    if (length == 0 || dst == src)        /* nothing to do */
  382. X        return;
  383. X
  384. X    /*
  385. X     * Macros: loop-t-times; and loop-t-times, t>0
  386. X     */
  387. X#define    TLOOP(s) if (t) TLOOP1(s)
  388. X#define    TLOOP1(s) do { s; } while (--t)
  389. X
  390. X    if ((unsigned long)dst < (unsigned long)src) {
  391. X        /*
  392. X         * Copy forward.
  393. X         */
  394. X        t = (int)src;    /* only need low bits */
  395. X        if ((t | (int)dst) & wmask) {
  396. X            /*
  397. X             * Try to align operands.  This cannot be done
  398. X             * unless the low bits match.
  399. X             */
  400. X            if ((t ^ (int)dst) & wmask || length < wsize)
  401. X                t = length;
  402. X            else
  403. X                t = wsize - (t & wmask);
  404. X            length -= t;
  405. X            TLOOP1(*dst++ = *src++);
  406. X        }
  407. X        /*
  408. X         * Copy whole words, then mop up any trailing bytes.
  409. X         */
  410. X        t = length / wsize;
  411. X        TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
  412. X        t = length & wmask;
  413. X        TLOOP(*dst++ = *src++);
  414. X    } else {
  415. X        /*
  416. X         * Copy backwards.  Otherwise essentially the same.
  417. X         * Alignment works as before, except that it takes
  418. X         * (t&wmask) bytes to align, not wsize-(t&wmask).
  419. X         */
  420. X        src += length;
  421. X        dst += length;
  422. X        t = (int)src;
  423. X        if ((t | (int)dst) & wmask) {
  424. X            if ((t ^ (int)dst) & wmask || length <= wsize)
  425. X                t = length;
  426. X            else
  427. X                t &= wmask;
  428. X            length -= t;
  429. X            TLOOP1(*--dst = *--src);
  430. X        }
  431. X        t = length / wsize;
  432. X        TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
  433. X        t = length & wmask;
  434. X        TLOOP(*--dst = *--src);
  435. X    }
  436. X    return;
  437. X}
  438. @@@End of lq-text/src/ozmahash/bcopy.c
  439. echo x - lq-text/src/ozmahash/big.c 1>&2
  440. sed 's/^X//' >lq-text/src/ozmahash/big.c <<'@@@End of lq-text/src/ozmahash/big.c'
  441. X/*-
  442. X * Copyright (c) 1990 The Regents of the University of California.
  443. X * All rights reserved.
  444. X *
  445. X * This code is derived from software contributed to Berkeley by
  446. X * Margo Seltzer.
  447. X *
  448. X * %sccs.include.redist.c%
  449. X */
  450. X
  451. X#if defined(LIBC_SCCS) && !defined(lint)
  452. Xstatic char sccsid[] = "%W% (Berkeley) %G%";
  453. X#endif /* LIBC_SCCS and not lint */
  454. X
  455. X/******************************************************************************
  456. X
  457. XPACKAGE: hash
  458. X
  459. XDESCRIPTION: 
  460. X    Big key/data handling for the hashing package.
  461. X
  462. XROUTINES: 
  463. X    External
  464. X    big_keydata
  465. X    big_split
  466. X    big_insert
  467. X    big_return
  468. X    big_delete
  469. X    find_last_page
  470. X    Internal
  471. X    collect_key
  472. X    collect_data
  473. X******************************************************************************/
  474. X/* Includes */
  475. X#include <sys/types.h>
  476. X#include <sys/file.h>
  477. X#include <assert.h>
  478. X#include <errno.h>
  479. X#include <db.h>
  480. X#include <hash.h>
  481. X#include <page.h>
  482. X#include <stdio.h>
  483. X
  484. X/* Externals */
  485. X/* buf.c */
  486. Xextern BUFHEAD *get_buf();
  487. X
  488. X/* page.c */
  489. Xextern BUFHEAD *add_ovflpage();
  490. X
  491. X/* My externals */
  492. Xextern int big_keydata();
  493. Xextern int big_split();
  494. Xextern int big_insert();
  495. Xextern int big_return();
  496. Xextern int big_delete();
  497. Xextern u_short find_last_page();
  498. Xextern int find_bigpair();
  499. X
  500. X/* My internals */
  501. Xstatic int collect_key();
  502. Xstatic int collect_data();
  503. X
  504. X#ifdef HASH_STATISTICS
  505. Xextern long hash_accesses, hash_collisions, hash_expansions, hash_overflows;
  506. X#endif
  507. X/*
  508. XBig_insert
  509. X
  510. XYou need to do an insert and the key/data pair is too big
  511. X0 ==> OK
  512. X-1 ==> ERROR
  513. X*/
  514. Xextern int
  515. Xbig_insert ( bufp, key, val )
  516. XBUFHEAD *bufp;
  517. XDBT    *key, *val;
  518. X{
  519. X    char    *cp = bufp->page;    /* Character pointer of p */
  520. X    register u_short    *p = (u_short *)cp;
  521. X    char    *key_data, *val_data;
  522. X    int        key_size, val_size;
  523. X    int        n;
  524. X    u_short    space, move_bytes, off;
  525. X
  526. X    key_data = key->data;
  527. X    key_size = key->size;
  528. X    val_data = val->data;
  529. X    val_size = val->size;
  530. X
  531. X    /* First move the Key */
  532. X    for ( space = FREESPACE(p) - BIGOVERHEAD; 
  533. X      key_size; 
  534. X      space = FREESPACE(p) - BIGOVERHEAD ) {
  535. X    move_bytes = MIN(space, key_size);
  536. X    off = OFFSET(p) - move_bytes;
  537. X    bcopy (key_data, cp+off, move_bytes );
  538. X    key_size -= move_bytes;
  539. X    key_data += move_bytes;
  540. X    n = p[0];
  541. X    p[++n] = off;
  542. X    p[0] = ++n;
  543. X    FREESPACE(p) = off - PAGE_META(n);
  544. X    OFFSET(p) = off;
  545. X    p[n] = PARTIAL_KEY;
  546. X    bufp = add_ovflpage(bufp);
  547. X    if ( !bufp ) {
  548. X        return(-1);
  549. X    }
  550. X    n = p[0];
  551. X    if ( !key_size ) {
  552. X        if ( FREESPACE(p) ) {
  553. X        move_bytes = MIN (FREESPACE(p), val_size);
  554. X        off = OFFSET(p) - move_bytes;
  555. X        p[n] = off;
  556. X        bcopy ( val_data, cp + off, move_bytes );
  557. X        val_data += move_bytes;
  558. X        val_size -= move_bytes;
  559. X        p[n-2] = FULL_KEY_DATA;
  560. X        FREESPACE(p) = FREESPACE(p) - move_bytes;
  561. X        OFFSET(p) = off;
  562. X        }
  563. X        else p[n-2] = FULL_KEY;
  564. X    }
  565. X    p = (u_short *)bufp->page;
  566. X    cp = bufp->page;
  567. X    bufp->flags |= BUF_MOD;
  568. X    }
  569. X
  570. X    /* Now move the data */
  571. X    for ( space = FREESPACE(p) - BIGOVERHEAD; 
  572. X      val_size; 
  573. X      space = FREESPACE(p) - BIGOVERHEAD ) {
  574. X    move_bytes = MIN(space, val_size);
  575. X    /*
  576. X        Here's the hack to make sure that if the data ends
  577. X        on the same page as the key ends, FREESPACE is
  578. X        at least one
  579. X    */
  580. X    if ( space == val_size && val_size == val->size ) {
  581. X        move_bytes--;
  582. X    }
  583. X    off = OFFSET(p) - move_bytes;
  584. X    bcopy (val_data, cp+off, move_bytes );
  585. X    val_size -= move_bytes;
  586. X    val_data += move_bytes;
  587. X    n = p[0];
  588. X    p[++n] = off;
  589. X    p[0] = ++n;
  590. X    FREESPACE(p) = off - PAGE_META(n);
  591. X    OFFSET(p) = off;
  592. X    if ( val_size ) {
  593. X        p[n] = FULL_KEY;
  594. X        bufp = add_ovflpage (bufp);
  595. X        if ( !bufp ) {
  596. X        return(-1);
  597. X        }
  598. X        cp = bufp->page;
  599. X        p = (u_short *)cp;
  600. X    } else {
  601. X        p[n] = FULL_KEY_DATA;
  602. X    }
  603. X    bufp->flags |= BUF_MOD;
  604. X    }
  605. X    return(0);
  606. X}
  607. X
  608. X/*
  609. X    Called when bufp's page  contains a partial key (index should be 1)
  610. X
  611. X    All pages in the big key/data pair except bufp are freed.  We cannot
  612. X    free bufp because the page pointing to it is lost and we can't
  613. X    get rid of its pointer.
  614. X
  615. X    Returns 0 => OK
  616. X        -1 => ERROR
  617. X*/
  618. Xextern int
  619. Xbig_delete (bufp, ndx)
  620. XBUFHEAD    *bufp;
  621. Xint    ndx;
  622. X{
  623. X    register    BUFHEAD        *rbufp = bufp;
  624. X    register    BUFHEAD        *last_bfp = NULL;
  625. X    char    *cp;
  626. X    u_short    *bp = (u_short *)bufp->page;
  627. X    u_short    *xbp;
  628. X    u_short    pageno = 0;
  629. X    u_short    off, free_sp;
  630. X    int    key_done = 0;
  631. X    int    n;
  632. X
  633. X    while (!key_done || (bp[2] != FULL_KEY_DATA)) {
  634. X        if ( bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA ) key_done = 1;
  635. X
  636. X        /*
  637. X        If there is freespace left on a FULL_KEY_DATA page,
  638. X        then the data is short and fits entirely on this
  639. X        page, and this is the last page.
  640. X        */
  641. X        if ( bp[2] == FULL_KEY_DATA && FREESPACE(bp) ) break;
  642. X        pageno = bp[bp[0]-1];
  643. X        rbufp->flags |= BUF_MOD;
  644. X        rbufp = get_buf ( pageno, rbufp, 0 );
  645. X        if ( last_bfp ) free_ovflpage(last_bfp);
  646. X        last_bfp = rbufp;
  647. X        if ( !rbufp ) return(-1);            /* Error */
  648. X        bp = (u_short *)rbufp->page;
  649. X    }
  650. X
  651. X    /* 
  652. X        If we get here then rbufp points to the last page of
  653. X        the big key/data pair.  Bufp points to the first
  654. X        one -- it should now be empty pointing to the next
  655. X        page after this pair.  Can't free it because we don't
  656. X        have the page pointing to it.
  657. X    */
  658. X
  659. X    /* This is information from the last page of the pair */
  660. X    n = bp[0];
  661. X    pageno = bp[n-1];
  662. X
  663. X    /* Now, bp is the first page of the pair */
  664. X    bp = (u_short *)bufp->page;
  665. X    if ( n > 2 ) {
  666. X        /* There is an overflow page */
  667. X        bp[1] = pageno;
  668. X        bp[2] = OVFLPAGE;
  669. X        bufp->ovfl = rbufp->ovfl;
  670. X    } else {
  671. X        /* This is the last page */
  672. X        bufp->ovfl = NULL;
  673. X    }
  674. X    n -= 2;
  675. X    bp[0] = n;
  676. X    FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
  677. X    OFFSET(bp) = hashp->BSIZE - 1;
  678. X
  679. X    bufp->flags |= BUF_MOD;
  680. X    if ( rbufp ) free_ovflpage(rbufp);
  681. X    if ( last_bfp != rbufp ) free_ovflpage(last_bfp);
  682. X
  683. X    hashp->NKEYS--;
  684. X    return(0);
  685. X}
  686. X
  687. X/*
  688. X    0 = key not found
  689. X    -1 = get next overflow page
  690. X    -2 means key not found and this is big key/data
  691. X    -3 error
  692. X*/
  693. Xextern int
  694. Xfind_bigpair(bufp, ndx, key, size )
  695. XBUFHEAD    *bufp;
  696. Xint    ndx;
  697. Xchar    *key;
  698. Xint    size;
  699. X{
  700. X    register    u_short    *bp = (u_short *)bufp->page;
  701. X    register    char    *p = bufp->page;
  702. X    int        ksize = size;
  703. X    char    *kkey = key;
  704. X    u_short    bytes;
  705. X
  706. X
  707. X    for ( bytes = hashp->BSIZE - bp[ndx]; 
  708. X      bytes <= size && bp[ndx+1] == PARTIAL_KEY; 
  709. X      bytes = hashp->BSIZE - bp[ndx] ) {
  710. X
  711. X    if ( bcmp ( p+bp[ndx], kkey, bytes ))return(-2);
  712. X    kkey += bytes;
  713. X    ksize -= bytes;
  714. X    bufp = get_buf ( bp[ndx+2], bufp, 0 );
  715. X    if ( !bufp ) {
  716. X        return(-3);
  717. X    }
  718. X    p = bufp->page;
  719. X    bp = (u_short *)p;
  720. X    ndx = 1;
  721. X    }
  722. X
  723. X    if ( (bytes != ksize) || bcmp ( p+bp[ndx], kkey, bytes )) {
  724. X#ifdef HASH_STATISTICS
  725. X    hash_collisions++;
  726. X#endif
  727. X    return(-2);
  728. X    }
  729. X    else return (ndx);
  730. X}
  731. X
  732. X
  733. X/*
  734. X    Given the buffer pointer of the first overflow page of a big pair, 
  735. X    find the end of the big pair
  736. X
  737. X    This will set bpp to the buffer header of the last page of the big pair.  
  738. X    It will return the pageno of the overflow page following the last page of 
  739. X    the pair; 0 if there isn't any (i.e. big pair is the last key in the 
  740. X    bucket)
  741. X*/
  742. Xextern u_short
  743. Xfind_last_page ( bpp )
  744. XBUFHEAD    **bpp;
  745. X{
  746. X    int    n;
  747. X    u_short    pageno;
  748. X    BUFHEAD    *bufp = *bpp;
  749. X    u_short    *bp = (u_short *)bufp->page;
  750. X
  751. X    while ( 1 ) {
  752. X        n = bp[0];
  753. X
  754. X        /*
  755. X        This is the last page if:
  756. X            the tag is FULL_KEY_DATA and either
  757. X                only 2 entries
  758. X                OVFLPAGE marker is explicit
  759. X                there is freespace on the page
  760. X        */
  761. X        if ( bp[2] == FULL_KEY_DATA &&
  762. X         ((n == 2) ||  (bp[n] == OVFLPAGE) || (FREESPACE(bp)) ) ) break;
  763. X
  764. X        pageno = bp[n-1];
  765. X        bufp = get_buf ( pageno, bufp, 0 );
  766. X        if ( !bufp ) return (0);        /* Need to indicate an error! */
  767. X        bp = (u_short *)bufp->page;
  768. X    }
  769. X
  770. X    *bpp = bufp;
  771. X    if ( bp[0] > 2 ) return ( bp[3] );
  772. X    else return(0);
  773. X}
  774. X
  775. X
  776. X/*
  777. X    Return the data for the key/data pair
  778. X    that begins on this page at this index
  779. X    (index should always be 1)
  780. X*/
  781. Xextern int
  782. Xbig_return ( bufp, ndx, val, set_current )
  783. XBUFHEAD    *bufp;
  784. Xint    ndx;
  785. XDBT    *val;
  786. Xint    set_current;
  787. X{
  788. X    BUFHEAD    *save_p;
  789. X    u_short    save_addr;
  790. X    u_short    *bp = (u_short *)bufp->page;
  791. X    u_short    off, len;
  792. X    char    *cp, *tp;
  793. X
  794. X    while ( bp[ndx+1] == PARTIAL_KEY ) {
  795. X    bufp = get_buf ( bp[bp[0]-1], bufp, 0 );
  796. X    if ( !bufp ) return(-1);
  797. X    bp = (u_short *)bufp->page;
  798. X    ndx = 1;
  799. X    }
  800. X
  801. X    if ( bp[ndx+1] == FULL_KEY ) {
  802. X    bufp = get_buf ( bp[bp[0]-1], bufp, 0 );
  803. X    if ( !bufp ) return(-1);
  804. X    bp = (u_short *)bufp->page;
  805. X    save_p = bufp;
  806. X    save_addr = save_p->addr;
  807. X    off = bp[1];
  808. X    len = 0;
  809. X    } else if (!FREESPACE(bp)) {
  810. X    /*
  811. X        This is a hack.  We can't distinguish between
  812. X        FULL_KEY_DATA that contains complete data or
  813. X        incomplete data, so we require that if the
  814. X        data  is complete, there is at least 1 byte
  815. X        of free space left.
  816. X    */
  817. X    off = bp[bp[0]];
  818. X    len = bp[1] - off;
  819. X    save_p = bufp;
  820. X    save_addr = bufp->addr;
  821. X    bufp = get_buf ( bp[bp[0]-1], bufp, 0 );
  822. X    if ( !bufp ) return(-1);
  823. X    bp = (u_short *)bufp->page;
  824. X    } else {
  825. X    /* The data is all on one page */
  826. X    tp = (char *)bp;
  827. X    off = bp[bp[0]];
  828. X    val->data = tp + off;
  829. X    val->size = bp[1] - off;
  830. X    if ( set_current ) {
  831. X        if ( bp[0] == 2 ) {        /* No more buckets in chain */
  832. X        hashp->cpage = NULL;
  833. X        hashp->cbucket++;
  834. X        hashp->cndx=1;
  835. X        } else  {
  836. X        hashp->cpage = get_buf ( bp[bp[0]-1], bufp, 0 );
  837. X        if ( !hashp->cpage )return(-1);
  838. X        hashp->cndx = 1;
  839. X        if ( !((u_short *)hashp->cpage->page)[0] ) {
  840. X            hashp->cbucket++;
  841. X            hashp->cpage = NULL;
  842. X        }
  843. X        }
  844. X    }
  845. X    return(0);
  846. X    }
  847. X    
  848. X    val->size = collect_data ( bufp, len, set_current );
  849. X    if ( val->size == -1 ) {
  850. X    return(-1);
  851. X    }
  852. X    if ( save_p->addr != save_addr ) {
  853. X    /* We are pretty short on buffers */
  854. X    errno = EINVAL;        /* OUT OF BUFFERS */
  855. X    return(-1);
  856. X    }
  857. X    bcopy ( (save_p->page)+off, hashp->tmp_buf, len );
  858. X    val->data = hashp->tmp_buf;
  859. X    return(0);
  860. X}
  861. X
  862. X/*
  863. X    Count how big the total datasize is by
  864. X    recursing through the pages.  Then allocate
  865. X    a buffer and copy the data as you recurse up.
  866. X*/
  867. Xstatic int
  868. Xcollect_data ( bufp, len, set )
  869. XBUFHEAD    *bufp;
  870. Xint    len;
  871. Xint    set;
  872. X{
  873. X    register    char    *p = bufp->page;
  874. X    register    u_short    *bp = (u_short *)p;
  875. X    u_short    save_addr;
  876. X    int    mylen, totlen;
  877. X    BUFHEAD    *xbp;
  878. X
  879. X    mylen = hashp->BSIZE - bp[1];
  880. X    save_addr = bufp->addr;
  881. X
  882. X    if ( bp[2] == FULL_KEY_DATA ) {    /* End of Data */
  883. X    totlen = len + mylen;
  884. X    if ( hashp->tmp_buf ) free (hashp->tmp_buf);
  885. X    hashp->tmp_buf = (char *)malloc ( totlen );
  886. X    if ( !hashp->tmp_buf ) {
  887. X        return(-1);
  888. X    }
  889. X    if ( set ) {
  890. X        hashp->cndx = 1;
  891. X        if ( bp[0] == 2 ) {        /* No more buckets in chain */
  892. X        hashp->cpage = NULL;
  893. X        hashp->cbucket++;
  894. X        } else  {
  895. X        hashp->cpage = get_buf ( bp[bp[0]-1], bufp, 0 );
  896. X        if (!hashp->cpage) {
  897. X            return(-1);
  898. X        } else if ( !((u_short *)hashp->cpage->page)[0] ) {
  899. X            hashp->cbucket++;
  900. X            hashp->cpage = NULL;
  901. X        }
  902. X        }
  903. X    }
  904. X    } else {
  905. X    xbp = get_buf ( bp[bp[0]-1], bufp, 0 );
  906. X    if ( !xbp || ((totlen = collect_data ( xbp, len + mylen, set )) < 1) ) {
  907. X        return(-1);
  908. X    }
  909. X    }
  910. X    if ( bufp->addr != save_addr ) {
  911. X    errno = EINVAL;        /* Out of buffers */
  912. X    return(-1);
  913. X    }
  914. X    bcopy ( (bufp->page) + bp[1], &hashp->tmp_buf[len], mylen );
  915. X    return ( totlen );
  916. X}
  917. X
  918. X/*
  919. X    Fill in the key and data
  920. X    for this big pair 
  921. X*/
  922. Xextern int
  923. Xbig_keydata ( bufp, ndx, key, val, set )
  924. XBUFHEAD    *bufp;
  925. Xint    ndx;
  926. XDBT    *key, *val;
  927. Xint    set;
  928. X{
  929. X    key->size = collect_key ( bufp, 0, val, set );
  930. X    if ( key->size == -1 ) {
  931. X    return (-1);
  932. X    }
  933. X    key->data = hashp->tmp_key;
  934. X    return(0);
  935. X}
  936. X
  937. X/*
  938. X    Count how big the total key size is by
  939. X    recursing through the pages.  Then collect
  940. X    the data, allocate a buffer and copy the key as
  941. X    you recurse up.
  942. X*/
  943. Xstatic int
  944. Xcollect_key ( bufp, len, val, set )
  945. XBUFHEAD    *bufp;
  946. Xint    len;
  947. XDBT    *val;
  948. Xint    set;
  949. X{
  950. X    char    *p = bufp->page;
  951. X    u_short    *bp = (u_short *)p;
  952. X    u_short    save_addr;
  953. X    int    mylen, totlen;
  954. X    BUFHEAD    *xbp;
  955. X
  956. X    mylen = hashp->BSIZE - bp[1];
  957. X
  958. X    save_addr = bufp->addr;
  959. X    totlen = len + mylen;
  960. X    if ( bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA ) {/* End of Key */
  961. X    if ( hashp->tmp_key ) free (hashp->tmp_key);
  962. X    hashp->tmp_key = (char *)malloc ( totlen );
  963. X    if ( !hashp->tmp_key ) {
  964. X        return(-1);
  965. X    }
  966. X    big_return ( bufp, 1, val, set );
  967. X    } else {
  968. X    xbp = get_buf (bp[bp[0]-1], bufp, 0);
  969. X    if ( !xbp || ((totlen = collect_key (xbp, totlen, val, set)) < 1 ) ) {
  970. X        return(-1);
  971. X    }
  972. X    }
  973. X    if ( bufp->addr != save_addr ) {
  974. X    errno = EINVAL;        /* MIS -- OUT OF BUFFERS */
  975. X    return (-1);
  976. X    }
  977. X    bcopy ( (bufp->page) + bp[1], &hashp->tmp_key[len], mylen );
  978. X    return ( totlen );
  979. X}
  980. X
  981. X
  982. X/*
  983. X    return 0 => OK
  984. X       -1 => error
  985. X*/
  986. Xextern int
  987. Xbig_split ( op, np, big_keyp, addr, obucket, ret )
  988. XBUFHEAD    *op;        /* Pointer to where to put keys that go in old bucket */
  989. XBUFHEAD    *np;        /* Pointer to new bucket page */
  990. XBUFHEAD    *big_keyp;    /* Pointer to first page containing the big key/data */
  991. Xu_short    addr;        /* Address of big_keyp */
  992. Xint    obucket;    /* Old Bucket */
  993. XSPLIT_RETURN    *ret;
  994. X{
  995. X    register    u_short    *prev_pagep;
  996. X    register    BUFHEAD    *tmpp;
  997. X    register    u_short     *tp;
  998. X    BUFHEAD    *bp = big_keyp;
  999. X    u_short    off, free_space;
  1000. X    u_short    n;
  1001. X
  1002. X    DBT        key, val;
  1003. X
  1004. X    int        change;
  1005. X
  1006. X    /* Now figure out where the big key/data goes */
  1007. X    if (big_keydata ( big_keyp, 1, &key, &val, 0 )) {
  1008. X    return(-1);
  1009. X    }
  1010. X    change = (call_hash ( key.data, key.size ) != obucket );
  1011. X
  1012. X    if ( ret->next_addr = find_last_page ( &big_keyp ) ) {
  1013. X    if (!(ret->nextp = get_buf ( ret->next_addr, big_keyp, 0 ))) {
  1014. X        return(-1);;
  1015. X    }
  1016. X    } else {
  1017. X    ret->nextp = NULL;
  1018. X    }
  1019. X
  1020. X    /* Now make one of np/op point to the big key/data pair */
  1021. X    assert(np->ovfl == NULL);
  1022. X    if ( change ) tmpp = np;
  1023. X    else tmpp = op;
  1024. X
  1025. X    tmpp->flags |= BUF_MOD;
  1026. X#ifdef DEBUG1
  1027. X    fprintf ( stderr, "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
  1028. X        (tmpp->ovfl?tmpp->ovfl->addr:0), 
  1029. X        (bp?bp->addr:0) );
  1030. X#endif
  1031. X    tmpp->ovfl = bp;        /* one of op/np point to big_keyp */
  1032. X    tp = (u_short *)tmpp->page;
  1033. X    assert ( FREESPACE(tp) >= OVFLSIZE);
  1034. X    n = tp[0];
  1035. X    off = OFFSET(tp);
  1036. X    free_space = FREESPACE(tp);
  1037. X    tp[++n] = addr;
  1038. X    tp[++n] = OVFLPAGE;
  1039. X    tp[0] = n;
  1040. X    OFFSET(tp) = off;
  1041. X    FREESPACE(tp) = free_space - OVFLSIZE;
  1042. X
  1043. X    /* 
  1044. X    Finally, set the new and old return values.
  1045. X    BIG_KEYP contains a pointer to the last page of the big key_data pair.
  1046. X    Make sure that big_keyp has no following page (2 elements) or create
  1047. X    an empty following page.
  1048. X    */
  1049. X
  1050. X    ret->newp = np;
  1051. X    ret->oldp = op;
  1052. X
  1053. X    tp = (u_short *)big_keyp->page;
  1054. X    big_keyp->flags |= BUF_MOD;
  1055. X    if ( tp[0] > 2 ) {
  1056. X    /* 
  1057. X        There may be either one or two offsets on this page 
  1058. X        If there is one, then the overflow page is linked on
  1059. X        normally and tp[4] is OVFLPAGE.  If there are two, tp[4]
  1060. X        contains the second offset and needs to get stuffed in
  1061. X        after the next overflow page is added
  1062. X    */
  1063. X    n = tp[4];        
  1064. X    free_space = FREESPACE(tp);
  1065. X    off = OFFSET(tp);
  1066. X    tp[0] -= 2;
  1067. X    FREESPACE(tp) = free_space + OVFLSIZE;
  1068. X    OFFSET(tp) = off;
  1069. X    tmpp = add_ovflpage ( big_keyp );
  1070. X    if ( !tmpp ) {
  1071. X        return(-1);
  1072. X    }
  1073. X    tp[4] = n;
  1074. X    } else {
  1075. X    tmpp = big_keyp;
  1076. X    }
  1077. X
  1078. X    if ( change ) ret->newp = tmpp;
  1079. X    else ret->oldp = tmpp;
  1080. X
  1081. X    return(0);
  1082. X}
  1083. @@@End of lq-text/src/ozmahash/big.c
  1084. echo x - lq-text/src/ozmahash/buf.c 1>&2
  1085. sed 's/^X//' >lq-text/src/ozmahash/buf.c <<'@@@End of lq-text/src/ozmahash/buf.c'
  1086. X/*-
  1087. X * Copyright (c) 1990 The Regents of the University of California.
  1088. X * All rights reserved.
  1089. X *
  1090. X * This code is derived from software contributed to Berkeley by
  1091. X * Margo Seltzer.
  1092. X *
  1093. X * %sccs.include.redist.c%
  1094. X */
  1095. X
  1096. X#if defined(LIBC_SCCS) && !defined(lint)
  1097. Xstatic char sccsid[] = "%W% (Berkeley) %G%";
  1098. X#endif /* LIBC_SCCS and not lint */
  1099. X/******************************************************************************
  1100. X
  1101. XPACKAGE: hash
  1102. X
  1103. XDESCRIPTION: 
  1104. X    Contains buffer management
  1105. X
  1106. XROUTINES: 
  1107. X    External
  1108. X    buf_init
  1109. X    get_buf
  1110. X    buf_free
  1111. X    reclaim_buf
  1112. X    Internal
  1113. X    newbuf
  1114. X
  1115. X******************************************************************************/
  1116. X#include <sys/types.h>
  1117. X#include <sys/file.h>
  1118. X#include <assert.h>
  1119. X#include <errno.h>
  1120. X#include <hash.h>
  1121. X#include <stdio.h>
  1122. X
  1123. X/* Externals */
  1124. Xextern HTAB    *hashp;
  1125. X
  1126. X/* My internals */
  1127. Xstatic BUFHEAD *newbuf();
  1128. X
  1129. X/* Unlink B from its place in the lru */
  1130. X#define BUF_REMOVE(B)            \
  1131. X{                    \
  1132. X    B->prev->next = B->next;        \
  1133. X    B->next->prev = B->prev;        \
  1134. X}
  1135. X
  1136. X/* Insert B after P */
  1137. X#define BUF_INSERT(B,P)            \
  1138. X{                    \
  1139. X    B->next = P->next;            \
  1140. X    B->prev = P;            \
  1141. X    P->next = B;            \
  1142. X    B->next->prev = B;            \
  1143. X}
  1144. X
  1145. X#define    MRU    hashp->bufhead.next
  1146. X#define    LRU    hashp->bufhead.prev
  1147. X
  1148. X#define MRU_INSERT(B)    BUF_INSERT(B,(&hashp->bufhead))
  1149. X#define LRU_INSERT(B)    BUF_INSERT(B,LRU)
  1150. X
  1151. X/*
  1152. X    We are looking for a buffer with address "addr".
  1153. X    If prev_bp is NULL, then address is a bucket index.
  1154. X    If prev_bp is not NULL, then it points to the page previous
  1155. X    to an overflow page that we are trying to find.
  1156. X
  1157. X    CAVEAT:  The buffer header accessed via prev_bp's ovfl field
  1158. X    may no longer be valid.  Therefore, you must always verify that
  1159. X    its address matches the address you are seeking.
  1160. X*/
  1161. Xextern BUFHEAD *
  1162. Xget_buf ( addr, prev_bp, newpage )
  1163. Xint    addr;
  1164. XBUFHEAD    *prev_bp;
  1165. Xint    newpage;        /* If prev_bp is set, indicates that this is
  1166. X                    a new overflow page */
  1167. X{
  1168. X    register int    segment_ndx;
  1169. X    register    BUFHEAD    *bp;
  1170. X    register    unsigned    is_disk = 0;
  1171. X    SEGMENT    segp;
  1172. X
  1173. X    if ( prev_bp ) {
  1174. X    bp = prev_bp->ovfl;
  1175. X    if ( !bp || (bp->addr != addr) ) bp = NULL;
  1176. X    if ( !newpage ) is_disk = BUF_DISK;
  1177. X    }
  1178. X    else {
  1179. X    /* Grab buffer out of directory */
  1180. X    segment_ndx = addr & ( hashp->SGSIZE - 1 );
  1181. X
  1182. X    /*
  1183. X     * valid segment ensured by call_hash()
  1184. X     */
  1185. X    segp = hashp->dir[addr >> hashp->SSHIFT];
  1186. X#ifdef DEBUG
  1187. X    assert(segp != NULL);
  1188. X#endif
  1189. X    bp = PTROF(segp[segment_ndx]);
  1190. X    is_disk = ISDISK(segp[segment_ndx]);
  1191. X    } 
  1192. X
  1193. X    if ( !bp ) {
  1194. X    bp = newbuf ( addr, prev_bp );
  1195. X    if ( !bp || get_page ( bp->page, addr, !prev_bp, (int)is_disk, 0 )) {
  1196. X        return(NULL);
  1197. X    }
  1198. X    if ( !prev_bp ) {
  1199. X        segp[segment_ndx] = (BUFHEAD *)((unsigned)bp | is_disk);
  1200. X    }
  1201. X    } else {
  1202. X    BUF_REMOVE ( bp );
  1203. X    MRU_INSERT ( bp );
  1204. X    }
  1205. X    return(bp);
  1206. X}
  1207. X
  1208. X/*
  1209. X    We need a buffer for this page. Either allocate one, or
  1210. X    evict a resident one (if we have as many buffers as we're
  1211. X    allowed) and put this one in.
  1212. X
  1213. X    If newbuf finds an error (returning NULL), it also sets errno
  1214. X*/
  1215. Xstatic BUFHEAD *
  1216. Xnewbuf ( addr, prev_bp )
  1217. Xint    addr;
  1218. XBUFHEAD    *prev_bp;
  1219. X{
  1220. X    register    BUFHEAD    *bp;    /* The buffer we're going to use */
  1221. X    register    BUFHEAD    *xbp;    /* Temp pointer */
  1222. X    register    BUFHEAD *next_xbp;
  1223. X    int    segment_ndx;
  1224. X    u_short    *shortp;
  1225. X    u_short    oaddr;
  1226. X    SEGMENT    segp;
  1227. X
  1228. X    if ( hashp->nbufs ) {
  1229. X    /* Allocate a new one */
  1230. X    bp = (BUFHEAD *)malloc ( sizeof (struct _bufhead) );
  1231. X    if ( !bp || !(bp->page = (char *)malloc ( hashp->BSIZE )) ) {
  1232. X        return (NULL);
  1233. X    }
  1234. X    hashp->nbufs--;
  1235. X    } else {
  1236. X    /* Kick someone out */
  1237. X    bp = LRU;
  1238. X    BUF_REMOVE( bp );
  1239. X    /* 
  1240. X        Set oaddr before put_page so that you get it 
  1241. X        before bytes are swapped
  1242. X    */
  1243. X    shortp = (u_short *)bp->page;
  1244. X    oaddr = shortp[shortp[0]-1];
  1245. X    if ( (bp->flags & BUF_MOD) && 
  1246. X         put_page(bp->page, bp->addr, (int)IS_BUCKET(bp->flags), 0) ) {
  1247. X        return(NULL);
  1248. X    }
  1249. X    /* 
  1250. X        Update the pointer to this page (i.e. invalidate it).
  1251. X
  1252. X        If this is a new file (i.e. we created it at open time), 
  1253. X        make sure that we mark pages which have been written to 
  1254. X        disk so we retrieve them from disk later, rather than
  1255. X        allocating new pages.
  1256. X    */
  1257. X
  1258. X    if ( IS_BUCKET(bp->flags)) {
  1259. X        segment_ndx = bp->addr & ( hashp->SGSIZE - 1 );
  1260. X
  1261. X        segp = hashp->dir[bp->addr >> hashp->SSHIFT];
  1262. X
  1263. X        assert(segp != NULL);
  1264. X
  1265. X        if ( hashp->new_file && 
  1266. X         ((bp->flags & BUF_MOD) || ISDISK(segp[segment_ndx])) ) {
  1267. X        segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
  1268. X        } else segp[segment_ndx] = NULL;
  1269. X    }
  1270. X
  1271. X    /*
  1272. X        Since overflow pages can only be access by means of
  1273. X        their bucket, free overflow pages associated with this
  1274. X        bucket.
  1275. X    */
  1276. X    for ( xbp = bp; xbp->ovfl; ) {
  1277. X
  1278. X        next_xbp = xbp->ovfl;
  1279. X        xbp->ovfl = 0;
  1280. X        xbp = next_xbp;
  1281. X
  1282. X        /* Check that ovfl pointer is up date */
  1283. X        if ( IS_BUCKET(xbp->flags) || (oaddr != xbp->addr) ) break;
  1284. X
  1285. X        shortp = (u_short *)xbp->page;
  1286. X        oaddr = shortp[shortp[0]-1];    /* set before put_page */
  1287. X        if ( (xbp->flags & BUF_MOD) &&
  1288. X        put_page ( xbp->page, xbp->addr, 0, 0 ) ) {
  1289. X        return(NULL);
  1290. X        }
  1291. X        xbp->addr = 0;
  1292. X        xbp->flags = 0;
  1293. X        BUF_REMOVE ( xbp );
  1294. X        LRU_INSERT ( xbp );
  1295. X    }
  1296. X    }
  1297. X
  1298. X    /* Now assign this buffer */
  1299. X    bp->addr = addr;
  1300. X#ifdef DEBUG1
  1301. X    fprintf ( stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", bp->addr,
  1302. X        (bp->ovfl?bp->ovfl->addr:0),  0);
  1303. X#endif
  1304. X    bp->ovfl = NULL;
  1305. X    if ( prev_bp ) {
  1306. X    /* 
  1307. X        If prev_bp is set, this is an overflow page, hook it in to the
  1308. X        buffer overflow links
  1309. X    */
  1310. X#ifdef DEBUG1
  1311. X    fprintf ( stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", prev_bp->addr,
  1312. X            (prev_bp->ovfl?bp->ovfl->addr:0),  
  1313. X            (bp?bp->addr: 0));
  1314. X#endif
  1315. X    prev_bp->ovfl = bp;
  1316. X    bp->flags = 0;
  1317. X    } else bp->flags = BUF_BUCKET;
  1318. X    MRU_INSERT ( bp );
  1319. X    return ( bp );
  1320. X}
  1321. X
  1322. Xextern void
  1323. Xbuf_init ( nbytes )
  1324. Xint    nbytes;
  1325. X{
  1326. X    int    npages;
  1327. X    BUFHEAD    *bfp = &(hashp->bufhead);
  1328. X
  1329. X    npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
  1330. X    npages = MAX ( npages, MIN_BUFFERS );
  1331. X
  1332. X    hashp->nbufs = npages;
  1333. X    bfp->next = bfp;
  1334. X    bfp->prev = bfp;
  1335. X    /*
  1336. X    This space is calloc'd so these are already null
  1337. X
  1338. X    bfp->ovfl = NULL;
  1339. X    bfp->flags = 0;
  1340. X    bfp->page = NULL;
  1341. X    bfp->addr = 0;
  1342. X    */
  1343. X}
  1344. X
  1345. Xextern int
  1346. Xbuf_free ( do_free, to_disk )
  1347. Xint    do_free;
  1348. Xint    to_disk;
  1349. X{
  1350. X    BUFHEAD    *bp;
  1351. X
  1352. X    /* Need to make sure that buffer manager has been initialized */
  1353. X    if ( !LRU ) {
  1354. X    return(0);
  1355. X    }
  1356. X
  1357. X    for ( bp = LRU; bp != &hashp->bufhead; ) {
  1358. X    /* Check that the buffer is valid */
  1359. X    if ( bp->addr || IS_BUCKET(bp->flags) ) {
  1360. X        if ( to_disk && (bp->flags & BUF_MOD) &&
  1361. X         put_page (bp->page, bp->addr, IS_BUCKET(bp->flags)), 0 ) {
  1362. X        return (-1);
  1363. X        }
  1364. X    }
  1365. X
  1366. X    /* Check if we are freeing stuff */
  1367. X    if ( do_free ) {
  1368. X        if ( bp->page ) free ( bp->page );
  1369. X        BUF_REMOVE(bp);
  1370. X        (void)free ( bp );
  1371. X        bp = LRU;
  1372. X    } else bp = bp->prev;
  1373. X    }
  1374. X
  1375. X    return(0);
  1376. X}
  1377. X
  1378. Xextern void
  1379. Xreclaim_buf ( bp )
  1380. XBUFHEAD    *bp;
  1381. X{
  1382. X    bp->ovfl = 0;
  1383. X    bp->addr = 0;
  1384. X    bp->flags = 0;
  1385. X    BUF_REMOVE ( bp );
  1386. X    LRU_INSERT ( bp );
  1387. X}
  1388. @@@End of lq-text/src/ozmahash/buf.c
  1389. echo x - lq-text/src/ozmahash/byte_order.c 1>&2
  1390. sed 's/^X//' >lq-text/src/ozmahash/byte_order.c <<'@@@End of lq-text/src/ozmahash/byte_order.c'
  1391. X/*-
  1392. X * Copyright (c) 1990 The Regents of the University of California.
  1393. X * All rights reserved.
  1394. X *
  1395. X * This code is derived from software contributed to Berkeley by
  1396. X * Margo Seltzer.
  1397. X *
  1398. X * %sccs.include.redist.c%
  1399. X */
  1400. X
  1401. X#if defined(LIBC_SCCS) && !defined(lint)
  1402. Xstatic char sccsid[] = "%W% (Berkeley) %G%";
  1403. X#endif /* LIBC_SCCS and not lint */
  1404. X
  1405. X#include <stdio.h>
  1406. Xmain ( argc, argv )
  1407. Xint    argc;
  1408. Xchar    **argv;
  1409. X{
  1410. X    int        num = 0x41424344;
  1411. X    if ( ((((char *)&num)[0]) == 0x41) && ((((char *)&num)[1]) == 0x42) &&
  1412. X     ((((char *)&num)[2]) == 0x43) && ((((char *)&num)[3]) == 0x44) ) {
  1413. X        printf ( "BIG ENDIAN\n" );
  1414. X    } else if ( ((((char *)&num)[3]) == 0x41) && 
  1415. X        ((((char *)&num)[2]) == 0x42) && 
  1416. X        ((((char *)&num)[1]) == 0x43) && 
  1417. X        ((((char *)&num)[0]) == 0x44) ) {
  1418. X        printf ( "LITTLE ENDIAN\n" );
  1419. X    } else {
  1420. X    printf ( "Odd Endian -- are you running on a PDP-11?\n");
  1421. X    }
  1422. X
  1423. X}
  1424. @@@End of lq-text/src/ozmahash/byte_order.c
  1425. echo x - lq-text/src/menu/error.c 1>&2
  1426. sed 's/^X//' >lq-text/src/menu/error.c <<'@@@End of lq-text/src/menu/error.c'
  1427. X/* Error.c -- print an error message and exit.
  1428. X * If we're in curses mode, do an endwin() first.
  1429. X *
  1430. X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/error.c,v 1.1 90/08/29 21:49:49 lee Rel1-10 $
  1431. X *
  1432. X * $Log:    error.c,v $
  1433. X * Revision 1.1  90/08/29  21:49:49  lee
  1434. X * Initial revision
  1435. X * 
  1436. X * Revision 2.1  89/08/07  13:49:36  lee
  1437. X * First fully working (V.3.2 only) release;
  1438. X * this is the baseline for future development.
  1439. X * 
  1440. X * Revision 1.2  89/08/04  17:59:14  lee
  1441. X * Fully working with Basic Functionality.
  1442. X * Scrolling menubar, scrolling menus, moveable Info windows.
  1443. X * 
  1444. X *
  1445. X */
  1446. X
  1447. X#include <stdio.h>
  1448. X#ifdef ultrix
  1449. X# include <cursesX.h>
  1450. X#else
  1451. X# include <curses.h>
  1452. X#endif
  1453. X#include <malloc.h>
  1454. X#include "internal.h"
  1455. X#include "error.h"
  1456. X
  1457. Xint InCurses = 0;
  1458. Xextern char *cmdname, *progname;
  1459. X
  1460. X/*PRINTFLIKE1*/
  1461. X/*VARARGS1*/
  1462. Xvoid
  1463. Xerror(Type, fmt, a1, a2, a3, a4)
  1464. X    int Type;
  1465. X    char *fmt;
  1466. X{
  1467. X    extern char *strchr();
  1468. X    char *p;
  1469. X    extern char *malloc();
  1470. X
  1471. X    if (InCurses) {
  1472. X    if (!(Type & (ERR_INTERNAL | ERR_MEMORY))) {
  1473. X        if ((p = malloc(500)) == (char *) 0) {
  1474. X        Type |= ERR_MEMORY;
  1475. X        } else {
  1476. X        (void) sprintf(p, fmt, a1, a2, a3, a4);
  1477. X        (void) ShowInfo(p, (WINDOW *) 0, COLS / 2 - 20, LINES / 2 - 4);
  1478. X        if (Type & ERR_FATAL) {
  1479. X            endwin();
  1480. X            exit(1);
  1481. X        } else {
  1482. X            return;
  1483. X        }
  1484. X        }
  1485. X    }
  1486. X    if (Type & ERR_FATAL) {
  1487. X        endwin();
  1488. X        exit(1);
  1489. X    }
  1490. X    }
  1491. X    if (InCurses) {
  1492. X    if (Type & ERR_FATAL) {
  1493. X        endwin();
  1494. X        InCurses = 0;
  1495. X    }
  1496. X    }
  1497. X    if (InCurses && !(Type & ERR_INTERNAL)) {
  1498. X    wmove(stdscr, 5, 0);
  1499. X    clrtoeol();
  1500. X    refresh();
  1501. X    }
  1502. X    if (cmdname) {
  1503. X    (void) fprintf(stderr, "%s: ", cmdname);
  1504. X    }
  1505. X    if (progname) {
  1506. X    (void) fprintf(stderr, "%s: ", progname);
  1507. X    }
  1508. X    (void) fprintf(stderr, fmt, a1, a2, a3, a4);
  1509. X    if (strchr(fmt, '\n') == (char *) 0) {
  1510. X    (void) fputc('\n', stderr);
  1511. X    }
  1512. X    if (InCurses) fputc('\r', stderr);
  1513. X    if (Type & ERR_FATAL) exit(-1);
  1514. X}
  1515. @@@End of lq-text/src/menu/error.c
  1516. echo x - lq-text/src/menu/error.h 1>&2
  1517. sed 's/^X//' >lq-text/src/menu/error.h <<'@@@End of lq-text/src/menu/error.h'
  1518. X/* Codes that can be passed to error()
  1519. X *
  1520. X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/error.h,v 1.1 90/08/29 21:49:53 lee Rel1-10 $
  1521. X *
  1522. X * $Log:    error.h,v $
  1523. X * Revision 1.1  90/08/29  21:49:53  lee
  1524. X * Initial revision
  1525. X * 
  1526. X * Revision 2.1  89/08/07  13:48:38  lee
  1527. X * First fully working (V.3.2 only) release;
  1528. X * this is the baseline for future development.
  1529. X * 
  1530. X * Revision 1.1  89/07/28  19:11:06  lee
  1531. X * Initial revision
  1532. X * 
  1533. X *
  1534. X */
  1535. X
  1536. Xextern void error();
  1537. X
  1538. X#define ERR_INTERNAL    01
  1539. X#define ERR_MEMORY    02
  1540. X#define ERR_FATAL    04
  1541. @@@End of lq-text/src/menu/error.h
  1542. echo x - lq-text/src/menu/internal.h 1>&2
  1543. sed 's/^X//' >lq-text/src/menu/internal.h <<'@@@End of lq-text/src/menu/internal.h'
  1544. X/* internal.h -- header file for internal use.
  1545. X *
  1546. X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/internal.h,v 1.1 90/08/29 21:50:36 lee Rel1-10 $
  1547. X *
  1548. X * $Log:    internal.h,v $
  1549. X * Revision 1.1  90/08/29  21:50:36  lee
  1550. X * Initial revision
  1551. X * 
  1552. X * Revision 2.1  89/08/07  13:49:27  lee
  1553. X * First fully working (V.3.2 only) release;
  1554. X * this is the baseline for future development.
  1555. X * 
  1556. X * Revision 1.1  89/07/27  11:39:40  lee
  1557. X * Initial revision
  1558. X * 
  1559. X *
  1560. X */
  1561. X
  1562. X/* Thanks to Henry Spencer (utzoo!henry) for this: */
  1563. X#define STREQ(boy,girl) ((*(boy)== *(girl))&&!strcmp((boy),(girl)))
  1564. X
  1565. X
  1566. X/* SAVEMENULINE is set if you want to the menus to hang down from
  1567. X * the bar when selected.  (this is default)
  1568. X * Otherwise, define MENUTEXTOVERBAR and recompile...
  1569. X * the top line of the menu goes on screen row MENUTOP.
  1570. X * If MENUTOP is >= 2, the top line of the menu is boxed.  Otherwise,
  1571. X * the first item in the menu goes on the menu line, overwriting it.
  1572. X * Only use this if you have (ROWS - 1) items on each menu...
  1573. X */
  1574. X
  1575. X#ifndef MENUTEXTOERBAR
  1576. X# define SAVEMENULINE
  1577. X#endif
  1578. X#define SAVEMENULINE
  1579. X#ifdef SAVEMENULINE
  1580. X  /* MENUTOP is the line on which pull-down menus start. */
  1581. X# ifndef MENUTOP
  1582. X#  define MENUTOP 2
  1583. X# endif /*!MENUTOP*/
  1584. X# if MENUTOP>1
  1585. X#  define MENUBOXONTOPLINE
  1586. X# endif
  1587. X#else
  1588. X# define MENUTOP 1
  1589. X#  undef MENUBOXONTOPLINE
  1590. X#endif
  1591. X
  1592. X#define new(type)    ((type *) malloc(sizeof(type)))
  1593. @@@End of lq-text/src/menu/internal.h
  1594. echo x - lq-text/src/menu/menu.h 1>&2
  1595. sed 's/^X//' >lq-text/src/menu/menu.h <<'@@@End of lq-text/src/menu/menu.h'
  1596. X#ifdef ultrix
  1597. X# include "ultrixhack.h"
  1598. X#endif
  1599. X/* menu.h -- user programs should include this after curses.h 
  1600. X *
  1601. X * $Header: /usr/src/cmd/lq-text/src/menu/RCS/menu.h,v 1.1 90/08/29 21:50:50 lee Rel1-10 $
  1602. X *
  1603. X * $Log:    menu.h,v $
  1604. X * Revision 1.1  90/08/29  21:50:50  lee
  1605. X * Initial revision
  1606. X * 
  1607. X * Revision 2.1  89/08/07  13:49:31  lee
  1608. X * First fully working (V.3.2 only) release;
  1609. X * this is the baseline for future development.
  1610. X * 
  1611. X * Revision 1.2  89/08/04  17:59:07  lee
  1612. X * Fully working with Basic Functionality.
  1613. X * Scrolling menubar, scrolling menus, moveable Info windows.
  1614. X * 
  1615. X * Revision 1.1  89/07/27  11:39:20  lee
  1616. X * Initial revision
  1617. X * 
  1618. X *
  1619. X */
  1620. X
  1621. X/* for errors... -- set this whenever initscr() is in effect */
  1622. Xextern int InCurses;
  1623. X
  1624. X/* A menu bar from a data structures (how quaint!) viewpoint:
  1625. X *
  1626. X *   File  Edit  *Implement*  Duration
  1627. X * -------------+---------------+------------------------------------
  1628. X *        | Tongs        |
  1629. X *        | *Whip******** |
  1630. X *        | Branding Iron |
  1631. X *        | Thumbscrew    |
  1632. X *        | Dead Fish    |
  1633. X *        +---------------+
  1634. X *
  1635. X * MenuBar ---> +-----------------------------------------------------
  1636. X *        |HowManyMenus = 4
  1637. X *        |SelectedMenu = 2
  1638. X *        |MenuBarId [internal] = 34 (say)
  1639. X *        |ScrollOffset = 0 // horizontal scrolling of bar
  1640. X *        |Menus--->an array of 4 menu structures:
  1641. X *        |     
  1642. X *
  1643. X * MenuBar->Menus[2] looks like this:
  1644. X *        +-----------------------------------------------------
  1645. X *        |Name = "Implement"
  1646. X *        |HowManyItems = 5
  1647. X *        |NeedToBox = 1
  1648. X *        |IsSelected = 1 // it's highlighted in the MenuBar
  1649. X *        |TopLineOnScreen = 0 // for vertical scrolling
  1650. X *        |PositionInBar = 13 // characters from the left
  1651. X *        |Width = 14 // length of widest item
  1652. X *        |SelectedLine = 1 // they're numbered from 0
  1653. X *        |MenuId [private] = 4097 (say)
  1654. X *        |Description = "Choose a torture implement..."
  1655. X *        |Items--->an array of 5 items:
  1656. X *        |
  1657. X *
  1658. X * MenuBar->Menus[2]->Items[1] looks like this:
  1659. X *        +-----------------------------------------------------
  1660. X *        |Function-->points to a function to be called when
  1661. X *        |Name = "Whip"
  1662. X *        |NameLength = 4 // strlen(Name), for speed
  1663. X *        |Description = "Cat O' Nine Tails"
  1664. X *        |LongText = "Ouch" // passed to Function().
  1665. X */
  1666. X
  1667. Xtypedef struct {
  1668. X    int (*Function)();
  1669. X    /* Function is called when the menu is selected.  If it is
  1670. X     * zero, you just get a beep(); this is intended for testing.
  1671. X     * The function is passed two arguments: a pointer to the menu
  1672. X     * which contained this item, and the item number.  In the
  1673. X     * "Whip" example above, it would be a pointer to the Implement
  1674. X     * menu, and the number "1".
  1675. X     * The LongText argumenht is intended for use by this function,
  1676. X     * although what it does with it is undefined.  For example,
  1677. X     * it could contain a shell command, or it could be a pointer
  1678. X     * into a table of statements to be interpreted, or....
  1679. X     */
  1680. X    char *Name;
  1681. X    /* Name is the string displayed in the menu itself.
  1682. X     */
  1683. X    unsigned short NameLength;
  1684. X    /* NameLength must either be 0 or strlen(Name).  In the former case,
  1685. X     * it will automatically be updated.  It is not clear that this is
  1686. X     * a big saving, so it may well go way soon.
  1687. X     */
  1688. X    char *Description;
  1689. X    /* pop-up box for help/explanation; when the item is highlighted,
  1690. X     * the user can press `?' or `x' and get this short explanation in
  1691. X     * a pop-up box.
  1692. X     */
  1693. X    char *LongText;
  1694. X    /* for use only by Function -- see the comment there.
  1695. X     */
  1696. X} t_MenuItem;
  1697. X
  1698. X/* For MenuStyle, see below */
  1699. X#ifndef MENUSTYLE_DEFAULT
  1700. X# define MENUSTYLE_DEFAULT 0
  1701. X#endif
  1702. X
  1703. X/* Each menu structure holds (a pointer to) a number of Items...*/
  1704. Xtypedef struct {
  1705. X    int HowManyItems;
  1706. X    /* This can of course be less than the real number, if you want to
  1707. X     * shorten a menu for some reason.  If there are more items than
  1708. X     * will fit on the screen, the menu can scroll vertically, so there
  1709. X     * is no limit imposed on this by the menu routines.  On the other
  1710. X     * hand, it would be so irritating to scroll through 1000 items that
  1711. X     * the list should preferably be under 20.
  1712. X     */
  1713. X    t_MenuItem *Items;
  1714. X    /* This is a pointer to a block of menus.
  1715. X     * A linked list might be better.
  1716. X     */
  1717. X    unsigned int MenuStyle;
  1718. X    /* currently always zero, as there is only one style.
  1719. X     * you can use MENUSTYLE_DEFAULT for this.
  1720. X     * A future style might have no box, just a line on the left.
  1721. X     */
  1722. X    unsigned int IsSelected : 1;
  1723. X    /* This is in case you are using interrupts to change menus.  You
  1724. X     * wouldn't want to delete or hide a selected menu!
  1725. X     * The software updates this, but otherwise ignores it.
  1726. X     */
  1727. X    int TopLineOnScreen;
  1728. X    /* This is for vertical scrolling;  if it's 13 (say), then the
  1729. X     * first 13 lines of the menu are not displayed -- If it was "1" in
  1730. X     * the example, "Whip" would be where "Tongs" are, and "Tongs"
  1731. X     * would not be displayed.
  1732. X     */
  1733. X    int PositionInBar;
  1734. X    /* Horizontal position of the left edge of the box.  This is set
  1735. X     * for each menu by ShowMenuBar() at each call.
  1736. X     */
  1737. X    int Width;
  1738. X    /* The same as the length of the longest item.
  1739. X     * If you change the items, set this to zero to force ShowMenuBar()
  1740. X     * or ShowMenu() to recalculate it from the Item->[*].Width entries,
  1741. X     * or using strlen() if necessary.
  1742. X     */
  1743. X    char *Name;
  1744. X    int NameLength;
  1745. X    /* This is the text displayed on the menu bar.
  1746. X     * NameLength is computed by ShowMenuBar(); the user should set it
  1747. X     * to zero to indicate that this is necessary, when the menu is
  1748. X     * created and whenever the name changes.
  1749. X     */
  1750. X    char *Description;
  1751. X    /* This should be a short (one line) description of the purpose
  1752. X     * of this menu.
  1753. X     */
  1754. X    int SelectedLine;
  1755. X    /* This is the currently highlighted line.  If you set it yourself,
  1756. X     * ShowMenu() will make this the highlighted item when it first
  1757. X     * displays the menu.  Subsequently, of course, the user will move
  1758. X     * it up or down at will...
  1759. X     * The default is zero, the first item.
  1760. X     */
  1761. X    /* private */ int MenuId;
  1762. X    /* Set this to zero. */
  1763. X} t_Menu;
  1764. X
  1765. X#define MENUMAXINBAR 30
  1766. X
  1767. X/* A Menu Bar... */
  1768. Xtypedef struct {
  1769. X    int HowManyMenus;
  1770. X    /* The number of menus in Menus[].  Only the first MENUMAXINBAR will
  1771. X     * be used, however.  Also, not all will be displayed on the screen...
  1772. X     * depending on how many fit.
  1773. X     */
  1774. X    int SelectedMenu;
  1775. X    /* This is the Menu whose name is highlighted.
  1776. X     * Default is zero; set it to something else if you want...
  1777. X     */
  1778. X    t_Menu *Menus[MENUMAXINBAR];
  1779. X    /* Pointers to the menu structures */
  1780. X    int ScrollOffset;
  1781. X    /* This is for horizontal scrolling.
  1782. X     * The default is zero, meaning that the first menu is as near to the
  1783. X     * left of the screen as it will go (there's a 2-char gap to make
  1784. X     * room for the left edge of the box).
  1785. X     */
  1786. X    /* private */ int MenuBarId;
  1787. X    /* Set this to zero. */
  1788. X} t_MenuBar;
  1789. X
  1790. X/* Some functions that you can arrange to have called by menu selection.
  1791. X * The functions in this table must all take two arguments, a t_Menu *
  1792. X * and an integer, which represents the (menu, item) combination that
  1793. X * was selected.
  1794. X * They should return either the integer or -1.
  1795. X * If they return -3 or -4, it's the same as if the user pressed the
  1796. X * left or right arrow keys instead of selecting.
  1797. X * If they return -5, it's as if they typed 'q' at the prompt.
  1798. X */
  1799. X
  1800. X/*PRINTFLIKE1*/
  1801. Xextern void error();
  1802. X
  1803. X/* A TextBox has the following structure:
  1804. X *
  1805. X * +------------------------------------------
  1806. X * | Name (optional, only displayed if != 0)
  1807. X * | Flags
  1808. X * |     BoldName
  1809. X * |    BoldText
  1810. X * |    CanEdit
  1811. X * |    IfChanged (set if the text has been edited)
  1812. X * | Window (0 if not allocated)
  1813. X * | tlx, tly -- where it is
  1814. X * | Height, Width -- how big it is (including the surrounding box)
  1815. X * | char *Text -- the text itself
  1816. X * | HowManyLines
  1817. X * | short *LineLengths --> pointer to array of line lengths
  1818. X * | HScrollPos, VScrollPos
  1819. X */
  1820. Xtypedef struct s_TextBox {
  1821. X    char *Name;
  1822. X    unsigned long flags;
  1823. X    WINDOW *Window;
  1824. X    short tlx, tly;
  1825. X    short Height, Width;
  1826. X    int HScrollPos, VScrollPos;
  1827. X    char *String;
  1828. X    int HowManyLines;
  1829. X    short *LineLengths;
  1830. X    int StringWidth;
  1831. X} t_StringBox;
  1832. X
  1833. @@@End of lq-text/src/menu/menu.h
  1834. echo end of part 11
  1835. -- 
  1836. Liam R. E. Quin,  lee@sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337
  1837.