home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Snippets / EMBL Search / Sources / hitstorage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-04  |  9.6 KB  |  424 lines  |  [TEXT/KAHL]

  1. /*
  2. *********************************************************************
  3. *    
  4. *    HitStorage.c
  5. *    Handling of results storage and hitlist management
  6. *
  7. *    Rainer Fuchs
  8. *    EMBL Data Library
  9. *    Postfach 10.2209
  10. *    D-6900 Heidelberg, FRG
  11. *    E-mail: fuchs@embl-heidelberg.de
  12. *
  13. *    Copyright © 1992 EMBL Data Library
  14. *        
  15. **********************************************************************
  16. *    
  17. */ 
  18.  
  19. #include <stdio.h>
  20.  
  21. #include "EMBL-Search.h"
  22. #include "EMBL-Search.rsrc.h"
  23.  
  24. /*
  25. ******************************* Prototypes ***************************
  26. */
  27.  
  28. #include "hitstorage.h"
  29. #include "util.h"
  30. #include "pstr.h"
  31. #include "window.h"
  32.  
  33. static Boolean NewDEBlock(CString80Hdl *newBlockPtr);
  34. static Boolean NewResultRec(ResultHdl *new);
  35.  
  36.  
  37. /*
  38. ********************************* Globals *****************************
  39. */
  40.  
  41. extern IndexFiles    gFileList;
  42. extern DBInfo        gDBInfo[DB_NUM];
  43. extern char            gError[256];
  44.  
  45.  
  46. /**************************************
  47. *    Allocates movable memory block for description line buffer
  48. *    Return value:    TRUE, if successful
  49. *                        FALSE, if error occurred
  50. *    Side-effect:    Handle to this block
  51. */
  52.  
  53. static Boolean    NewDEBlock(CString80Hdl *newBlockPtr)
  54. {
  55.     *newBlockPtr = (CString80Hdl)NewHandleClear((Size)MAXBUFLINES * sizeof (CString80));
  56.     return( *newBlockPtr != NULL );
  57. }
  58.  
  59.  
  60. /**************************************
  61. *    Fill description line buffer from disk so that "from" is in buffer.
  62. *    To avoid continous loading when a user browses through the results,
  63. *    the buffer is filled (if possible) such that "from" is in the middle of
  64. *    the buffer.
  65. *    Return value:    TRUE, if successful
  66. *                        FALSE, if error occurred
  67. */
  68.  
  69. Boolean FillDEBuffer(ResultHdl resHdl,short first, Boolean bCache)
  70. {
  71.     short                fd;
  72.     SignedByte        oldDEState,oldHlState;
  73.     short                i,j;
  74.     u_long            pos;
  75.     long                size,count;
  76.     CString80Hdl    descBufHdl = (**resHdl).descBufHdl;
  77.     HitlistHdl         hlHdl = (**resHdl).hlHdl;
  78.     Str255            indexName,lenStr;
  79.     DescRec            rec;
  80.     char                *descPtr;
  81.     OSErr                err = noErr;
  82.     DialogPtr        myDialog;
  83.     
  84.     /* calculate first hit to be loaded. The size of the buffer guarantees
  85.         that we always load at least two screen fulls */
  86.     if(bCache) {
  87.         if (first >= MAXBUFLINES/2)
  88.             first -= MAXBUFLINES/2;
  89.         else
  90.             first = 0;
  91.     }
  92.     
  93.     /* open short description index */
  94.     pstrcpy(indexName,gFileList.briefIdxFName);
  95.     if(OpenMacFileReadOnly(indexName,gDBInfo[(**resHdl).dbcode].InxWDRefNum, &fd, TRUE) != noErr )
  96.         return(FALSE);
  97.     
  98.     /* Lock blocks */
  99.     oldDEState = LockHandleHigh((Handle)descBufHdl);
  100.     oldHlState = LockHandleHigh((Handle)hlHdl);
  101.  
  102.     CenterDA('DLOG',FETCHTITLES_DLG,50);
  103.     myDialog = GetNewDialog(FETCHTITLES_DLG,NULL,(WindowPtr)-1);
  104.     if(myDialog) {
  105.         ShowWindow(myDialog);
  106.         DrawDialog(myDialog);
  107.     }
  108.     
  109.     size = sizeof(DescRec);
  110.     for(    i=first,j=0;
  111.             i < first+MAXBUFLINES && i < (**resHdl).nhits;
  112.             ++i,++j) {
  113.         count = size;
  114.         pos = ( (*hlHdl + i)->ename_rec );
  115.         
  116.         if( (err = SetFPos(fd,fsFromStart,pos*size+sizeof(Header))) != noErr) {
  117.             sprintf(gError,LoadErrorStr(ERR_READFILE,FALSE),
  118.                         PtoCstr(indexName),err );
  119.             ErrorMsg(0);
  120.             break;
  121.         }
  122.         
  123.         RotateWaitCursor();
  124.         if( (err=ReadMacFile(fd,&count,&rec,indexName,TRUE)) != noErr )
  125.             break;
  126.         
  127.         descPtr = (char *)(*descBufHdl + j);
  128.         NumToString((long)ConvertLong(&rec.seqlen),lenStr);
  129.         sprintf(descPtr,"%10.10s %7.7s %6.6s %.54s",
  130.                     rec.entryname,rec.accno,PtoCstr(lenStr),rec.description);
  131.         CtoPstr(descPtr);
  132.     }
  133.  
  134.     if (myDialog) DisposeDialog(myDialog);
  135.  
  136.     FSClose(fd);
  137.     HSetState((Handle)descBufHdl,oldDEState);
  138.     HSetState((Handle)hlHdl,oldHlState);
  139.     (**resHdl).buftop = first;
  140.  
  141.     return(err == noErr);
  142. }
  143.  
  144.  
  145. /**************************************
  146. *    Allocates a hitlist
  147. *    Return value:    TRUE, if successful
  148. *                        FALSE, if error occurred
  149. *    Side-effect:    Handle to the new block,
  150. */
  151.  
  152. Boolean NewHitlist(HitmapHdl hitmapHdl,short dbcode, HitlistHdl *new, short *nhits)
  153. {
  154.     register long    i,j,size;
  155.     HitlistHdl        hlHdl;
  156.     SignedByte        oldState;
  157.     register long    *ptr;
  158.     
  159.     /* allocate empty hitlist */
  160.     *new = (HitlistHdl)NewHandle(0L);
  161.     if(*new != NULL) {
  162.         hlHdl = *new;
  163.         *nhits = 0;
  164.  
  165. /*        for (i=0; i<gDBInfo[dbcode].ename_nrec;++i) {*/
  166. /*            if(BitTst(*hitmapHdl,i)) {*/
  167. /*                ++(*nhits);*/
  168. /*                */
  169. /*                SetHandleSize( *new, *nhits * (long)sizeof(HitlistRec) );*/
  170. /*                if( MemError() != noErr ) {*/
  171. /*                    DisposHandle((Handle)*new);*/
  172. /*                    return( ErrorMsg(ERR_HITLISTEXT,NULL) );*/
  173. /*                }*/
  174. /*                */
  175. /*                (**new)[*nhits-1].ename_rec = i;*/
  176. /*                SetSelectState(*new,*nhits-1,FALSE);*/
  177. /*            }*/
  178. /*        }*/
  179.  
  180.         /* look through hitmap */
  181.         oldState = MyHLock((Handle)hitmapHdl);
  182.         ptr = *hitmapHdl;
  183.         
  184.         /* Assuming that hits are rare we do not test bit by bit, but check each long
  185.             word in the hitmap, eg 32 bits in one go. Only if a long word is not zero,
  186.             we check individual bits */
  187.         size = GetHandleSize((Handle)hitmapHdl)/4;
  188.         for (i=0; i<size;++i,++ptr) {
  189.             if(*ptr) {
  190.                 for(j=0;j<32;++j) {
  191.                     if(BitTst(ptr,j)) {
  192.                         /* for each hit we add a new record to the hitlist */
  193.                         ++(*nhits);
  194.                         
  195.                         SetHandleSize( (Handle)*new, *nhits * sizeof(HitlistRec) );
  196.                         if( MemError() != noErr ) {
  197.                             DisposHandle((Handle)*new);
  198.                             HSetState((Handle)hitmapHdl,oldState);
  199.                             return( ErrorMsg(ERR_HITLISTEXT) );
  200.                         }
  201.                         
  202.                         (**new)[*nhits-1].ename_rec = 32L * i + j;
  203.                         SetSelectState(*new,*nhits-1,FALSE);
  204.                     }
  205.                 }
  206.             }
  207.         }
  208.         HSetState((Handle)hitmapHdl,oldState);
  209.     }
  210.     
  211.     return( *new != NULL );
  212. }
  213.  
  214.  
  215. /**************************************
  216. *    Allocates relocatable memory block for result record
  217. *    Return value:    TRUE, if successful
  218. *                        FALSE, if error occurred
  219. *    Side-effect:    Handle to this block
  220. */
  221.  
  222. static Boolean NewResultRec(ResultHdl *new)
  223. {
  224.     *new = (ResultHdl)NewHandleClear(sizeof(ResultRec));
  225.     return( *new != NULL );
  226. }
  227.  
  228.  
  229. /**************************************
  230. *    Gets a new result record, incl. description line buffer, and initialises it
  231. *    Return values:
  232. *    Return value:    TRUE, if successful
  233. *                        FALSE, if error occurred
  234. *    Side effect:    Handle to new result record
  235. */
  236.  
  237. Boolean InitResultRec(ResultHdl *new, short dbcode, HitmapHdl hitmapHdl,
  238.                     QueryHdl queryHdl)
  239. {
  240.     ResultPtr    resPtr;
  241.     HitlistHdl    hlHdl;
  242.     short            nhits;
  243.     
  244.     if( new == NULL )
  245.         return(FALSE);
  246.         
  247.     /* Allocate memory for result record */
  248.     if ( !NewResultRec(new) )
  249.         return( FALSE );
  250.     
  251.     /* Get a pointer to it */
  252.     LockHandleHigh((Handle)*new);
  253.     resPtr = (ResultPtr)**new;
  254.     
  255.     /* Allocate memory for description line buffer */
  256.     if ( !NewDEBlock(&resPtr->descBufHdl) ) {
  257.         DisposHandle((Handle)*new);
  258.         *new = NULL;
  259.         return(FALSE);
  260.     }
  261.     
  262.     /* Allocate memory for hitlist */
  263.     if ( !NewHitlist(hitmapHdl,dbcode,&hlHdl,&nhits) ) {
  264.         DisposHandle((Handle)resPtr->descBufHdl);
  265.         DisposHandle((Handle)*new);
  266.         *new = NULL;
  267.         return(FALSE);
  268.     }
  269.     
  270.     /* Anchor hitlist to this result record */
  271.     resPtr->hlHdl = hlHdl;
  272.     resPtr->nhits = nhits;
  273.     
  274.     /* Anchor hitmap to result record */
  275.     resPtr->hitmapHdl = hitmapHdl;
  276.     
  277.     /* Anchor query record to result record */
  278.     resPtr->queryHdl = queryHdl;
  279.     
  280.     /* Init other fields */
  281.     resPtr->buftop = 0;
  282.     resPtr->nsel = 0;
  283.     resPtr->dbcode = dbcode;
  284.     HUnlock((Handle)*new);
  285.     return(TRUE);
  286. }
  287.  
  288.  
  289. /**************************************
  290. *    Dispose of contents of an existing result record
  291. *    Return value:    none
  292. */
  293.  
  294. void DisposeResRec(ResultHdl resRecHdl)
  295. {
  296.     ResultPtr resPtr;
  297.     
  298.     if(resRecHdl == NULL)
  299.         return;
  300.     
  301.     /* Get a pointer to the result record */
  302.     LockHandleHigh((Handle)resRecHdl);
  303.     resPtr = *resRecHdl;
  304.     
  305.     /* Free memory occupied by hitlist and description line buffers */
  306.     if( resPtr->hlHdl != NULL)
  307.         DisposHandle((Handle)resPtr->hlHdl);
  308.     
  309.     if( resPtr->descBufHdl != NULL)
  310.         DisposHandle((Handle)resPtr->descBufHdl);
  311.         
  312.     if( resPtr->hitmapHdl != NULL )
  313.         DisposHandle((Handle)resPtr->hitmapHdl);
  314.  
  315.     if( resPtr->queryHdl != NULL )
  316.         DisposHandle((Handle)resPtr->queryHdl);
  317.     
  318.     HUnlock((Handle)resRecHdl);
  319. }
  320.  
  321.  
  322. /**************************************
  323. *    See whether a result record is selected
  324. *    Return value:    TRUE, if selected
  325. *                        FALSE, if not
  326. */
  327.  
  328. Boolean GetSelectState(HitlistHdl hlHdl, short pos)
  329. {
  330.     return((*hlHdl)[pos].flags.selected);
  331. }
  332.  
  333.  
  334. /**************************************
  335. *    Select/deselect a result record
  336. *    Return value:    none
  337. */
  338.  
  339. void SetSelectState(HitlistHdl hlHdl, short pos, Boolean state)
  340. {
  341.     (*hlHdl)[pos].flags.selected = state;
  342. }
  343.  
  344.  
  345. /**************************************
  346. *    Allocate new hitmap. We always create multiples of "long", ie 32 bits.
  347. *    Return value:    TRUE, if selected
  348. *                        FALSE, if not
  349. *    Side-effect:    Handle to new block
  350. */
  351.  
  352. Boolean NewHitmap(HitmapHdl *new, short dbcode)
  353. {
  354.     register long    i;
  355.     long                nlong;
  356.     
  357.     /* calculate number of long words necessary to hold hitmap. */
  358.     nlong = (gDBInfo[dbcode].ename_nrec-1)/32 + 1;
  359.     
  360.     *new = (HitmapHdl) NewHandleClear((Size)nlong * 4L);
  361. /*    if(*new) {
  362.         for(i=0;i<nlong; ++i)
  363.             (**new)[i] = 0L;
  364.     }
  365. */
  366.     
  367.     return( *new != NULL );
  368. }
  369.  
  370.  
  371. /**************************************
  372. *    Logical Or hitmap 1 with hitmap 2
  373. *    Return value:    none
  374. *    Side-effect:    Result of logical Or in hmHdl1
  375. */
  376.  
  377. void OrHitmaps(HitmapHdl hmHdl1, HitmapHdl hmHdl2)
  378. {
  379.     register long    i;
  380.     long                size = GetHandleSize((Handle)hmHdl1)/4;
  381.     
  382.     if(hmHdl1 == hmHdl2)
  383.         return;
  384.         
  385.     for(i=0;i<size;++i)
  386.         (*hmHdl1)[i] |= (*hmHdl2)[i];
  387. }
  388.  
  389.  
  390. /**************************************
  391. *    Logical And hitmap 1 with hitmap 2
  392. *    Return value:    none
  393. *    Side-effect:    Result of logical And in hmHdl1
  394. */
  395.  
  396. void AndHitmaps(HitmapHdl hmHdl1, HitmapHdl hmHdl2)
  397. {
  398.     register long    i;
  399.     long                size = GetHandleSize((Handle)hmHdl1)/4;
  400.     
  401.     if(hmHdl1 == hmHdl2)
  402.         return;
  403.  
  404.     for(i=0;i<size;++i)
  405.         (*hmHdl1)[i] &= (*hmHdl2)[i];
  406. }
  407.  
  408. /**************************************
  409. *    Logical Not hitmap
  410. *    Return value:    none
  411. *    Side-effect:    Result of logical Not in hmHdl
  412. */
  413.  
  414. void NotHitmap(HitmapHdl hmHdl)
  415. {
  416.     register long    i;
  417.     long                size = GetHandleSize((Handle)hmHdl)/4;
  418.     
  419.     if(hmHdl == NULL)
  420.         return;
  421.  
  422.     for(i=0;i<size;++i)
  423.         (*hmHdl)[i] = ~(*hmHdl)[i];
  424. }