home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / fsrc1241.zip / markmanage.c < prev    next >
C/C++ Source or Header  |  1999-02-14  |  39KB  |  963 lines

  1. /*---------------------------------------------------------------------------+
  2.  | Titel: MARKMANAGE.C                                                       |
  3.  +-----------------------------------------+---------------------------------+
  4.  | Erstellt von: Michael Hohner            | Am: 27.08.1994                  |
  5.  +-----------------------------------------+---------------------------------+
  6.  | System: OS/2 2.x                                                          |
  7.  +---------------------------------------------------------------------------+
  8.  | Beschreibung:                                                             |
  9.  |                                                                           |
  10.  |    Verwaltung der Markierungen in Ketten und Buckets                      |
  11.  |                                                                           |
  12.  |                                                                           |
  13.  +---------------------------------------------------------------------------+
  14.  | Bemerkungen:                                                              |
  15.  +---------------------------------------------------------------------------*/
  16.  
  17. /*----------------------------- Header-Dateien ------------------------------*/
  18.  
  19. #define INCL_PM
  20. #define INCL_DOSSEMAPHORES
  21. #include <os2.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "main.h"
  25. #include "structs.h"
  26. #include "msgheader.h"
  27. #include "markmanage.h"
  28. #include "areaman\areaman.h"
  29.  
  30. /*--------------------------------- Defines ---------------------------------*/
  31.  
  32. /*---------------------------------- Typen ----------------------------------*/
  33.  
  34. /*---------------------------- Globale Variablen ----------------------------*/
  35.  
  36. /*----------------------- interne Funktionsprototypen -----------------------*/
  37.  
  38. static PMARKERAREA FindMarkerArea(PMARKERLIST pList, PCHAR pchAreaTag);
  39. static PMARKERBUCKET FindMarkerBucket(PMARKERAREA pArea, ULONG ulMsgID, PLONG plFoundIndex);
  40. static int SetAreaToFront(PMARKERLIST pList, PMARKERAREA pArea);
  41. static ULONG CalcAreaSize(PMARKERAREA pArea);
  42. static int CopyMarkerItems(PMARKERAREA pArea, PMARKERITEM pDest);
  43. static int LoadMarkerItems(PMARKERAREA pArea, PMARKERITEM pSrc, ULONG ulSizeBuffer);
  44.  
  45. /*---------------------------------------------------------------------------*/
  46. /* Funktionsname: MarkMessage                                                */
  47. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  48. /* Beschreibung: Nimmt eine Message in die Markierungs-Liste auf             */
  49. /*                                                                           */
  50. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  51. /* Parameter: pList: Markierungs-Liste                                       */
  52. /*            pchAreaTag: Area-Tag                                           */
  53. /*            ulMsgID:    Message-ID                                         */
  54. /*            ulMsgNr:    Message-Nummer                                     */
  55. /*            pHeader:    Message-Header                                     */
  56. /*            pchFindText: Suchtext (im Body)                                */
  57. /*            ulFlags:    Markierungs-Flags (MARKFLAG_*)                     */
  58. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  59. /* Rückgabewerte: 0  OK                                                      */
  60. /*                1  war schon markiert                                      */
  61. /*                2  Fehler                                                  */
  62. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  63. /* Sonstiges:                                                                */
  64. /*                                                                           */
  65. /*---------------------------------------------------------------------------*/
  66.  
  67. int MarkMessage(PMARKERLIST pList, PCHAR pchAreaTag, ULONG ulMsgID, ULONG ulMsgNr,
  68.                 MSGHEADER *pHeader, PCHAR pchFindText, ULONG ulFlags, ULONG ulHow, ULONG ulWhere)
  69. {
  70.    PMARKERAREA pArea=NULL;
  71.    PMARKERBUCKET pBucket=NULL;
  72.    LONG lFoundIndex = -1;
  73.    int i=0;
  74.  
  75.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  76.  
  77.    /* Area suchen */
  78.    pArea = FindMarkerArea(pList, pchAreaTag);
  79.  
  80.    if (pArea)
  81.    {
  82.       /* gefunden, an den Anfang setzen */
  83.       SetAreaToFront(pList, pArea);
  84.    }
  85.    else
  86.    {
  87.       /* nicht gefunden, neue Area anlegen */
  88.       pArea = calloc(1, sizeof(MARKERAREA));
  89.  
  90.       /* vorne einhaengen */
  91.       if (pList->pAreas)
  92.       {
  93.          pArea->next = pList->pAreas;
  94.          pList->pAreas->prev = pArea;
  95.          pList->pAreas = pArea;
  96.       }
  97.       else
  98.          pList->pAreas = pArea;
  99.  
  100.       /* Daten setzen */
  101.       memcpy(pArea->pchAreaTag, pchAreaTag, LEN_AREATAG);
  102.    }
  103.  
  104.    /* pArea zeigt nun auf eine existierende oder neue Area */
  105.  
  106.    /* Message suchen */
  107.    pBucket = FindMarkerBucket(pArea, ulMsgID, &lFoundIndex);
  108.  
  109.    if (pBucket)
  110.    {
  111.       /* Bucket gefunden, Index pruefen */
  112.       if (lFoundIndex >= 0)
  113.       {
  114.          int ret;
  115.  
  116.          /* Message war schon markiert, nur Flags updaten */
  117.          if (pBucket->aItems[lFoundIndex].ulFlags & ulFlags)
  118.             ret = 1;
  119.          else
  120.             ret = 0;
  121.          pBucket->aItems[lFoundIndex].ulFlags |= ulFlags;
  122.          pArea->bDirty = TRUE;
  123.          pList->bDirty = TRUE;
  124.  
  125.          DosReleaseMutexSem(pList->hmtxAccess);
  126.  
  127.          return ret;
  128.       }
  129.    }
  130.    else
  131.    {
  132.       /* nicht gefunden, kein Bucket, neuen Bucket */
  133.       pBucket = calloc(1, sizeof(MARKERBUCKET));
  134.       pArea->pBuckets = pBucket;
  135.    }
  136.  
  137.    /* pBucket zeigt auf den Ziel-Bucket, evtl. ein neuer */
  138.    if (pBucket->ulCountItems == SIZE_BUCKET)
  139.    {
  140.       /* Bucket ist voll, aufteilen */
  141.       PMARKERBUCKET pBucket2;
  142.  
  143.       pBucket2 = calloc(1, sizeof(MARKERBUCKET));
  144.       pBucket2->next = pBucket->next;
  145.       pBucket2->prev = pBucket;
  146.       if (pBucket->next)
  147.          pBucket->next->prev = pBucket2;
  148.       pBucket->next = pBucket2;
  149.  
  150.       pBucket2->ulCountItems= SIZE_BUCKET/2;
  151.       pBucket->ulCountItems= SIZE_BUCKET/2;
  152.       memcpy(pBucket2->aItems, &(pBucket->aItems[SIZE_BUCKET/2]), (SIZE_BUCKET/2)*sizeof(MARKERITEM));
  153.  
  154.       /* pruefen, in welchen der zwei Buckets die Message soll */
  155.       if (pBucket2->aItems[0].ulMsgID <= ulMsgID)
  156.          pBucket = pBucket2;
  157.    }
  158.  
  159.    /* pBucket zeigt auf ein Bucket mit einem freien Platz */
  160.  
  161.    /* Einfuegestelle suchen */
  162.    i=0;
  163.    while(i < pBucket->ulCountItems && pBucket->aItems[i].ulMsgID <= ulMsgID)
  164.       i++;
  165.  
  166.    if (i < pBucket->ulCountItems)
  167.    {
  168.       /* mittendrin, nach hinten rutschen */
  169.       memmove(&pBucket->aItems[i+1], &pBucket->aItems[i], (pBucket->ulCountItems-i)*sizeof(MARKERITEM));
  170.    }
  171.  
  172.    pBucket->ulCountItems++;
  173.  
  174.    /* Daten kopieren */
  175.    pBucket->aItems[i].ulMsgID = ulMsgID;
  176.    pBucket->aItems[i].ulMsgNr = ulMsgNr;
  177.    pBucket->aItems[i].ulFlags = ulFlags;
  178.    pBucket->aItems[i].ulHow   = ulHow;
  179.    pBucket->aItems[i].ulWhere = ulWhere;
  180.    memcpy(pBucket->aItems[i].pchFrom, pHeader->pchFromName, LEN_USERNAME);
  181.    memcpy(pBucket->aItems[i].pchSubj, pHeader->pchSubject, LEN_SUBJECT);
  182.    if (pchFindText)
  183.       strncpy(pBucket->aItems[i].pchFindText, pchFindText, LEN_FINDTEXT);
  184.    else
  185.       pBucket->aItems[i].pchFindText[0]=0;
  186.  
  187.    /* Dirty-Flags setzen */
  188.    pArea->bDirty = TRUE;
  189.    pList->bDirty = TRUE;
  190.  
  191.    DosReleaseMutexSem(pList->hmtxAccess);
  192.  
  193.    return 0;
  194. }
  195.  
  196. /*---------------------------------------------------------------------------*/
  197. /* Funktionsname: UnmarkMessage                                              */
  198. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  199. /* Beschreibung: Entfernt eine Message aus der Markierungsliste              */
  200. /*                                                                           */
  201. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  202. /* Parameter: pList: Markierungs-Liste                                       */
  203. /*            pchAreaTag: Area-Tag                                           */
  204. /*            ulMsgID:    Message-ID                                         */
  205. /*            ulFlags:    Markierungs-Flags (MARKFLAG_*)                     */
  206. /*                                                                           */
  207. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  208. /* Rückgabewerte: 0  OK                                                      */
  209. /*                1  nicht gefunden                                          */
  210. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  211. /* Sonstiges:                                                                */
  212. /*                                                                           */
  213. /*---------------------------------------------------------------------------*/
  214.  
  215. int UnmarkMessage(PMARKERLIST pList, PCHAR pchAreaTag, ULONG ulMsgID, ULONG ulFlags)
  216. {
  217.    PMARKERAREA pArea=NULL;
  218.    PMARKERBUCKET pBucket=NULL;
  219.    LONG lFoundIndex=-1;
  220.  
  221.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  222.  
  223.    /* Area suchen */
  224.    pArea = FindMarkerArea(pList, pchAreaTag);
  225.    if (pArea)
  226.    {
  227.       SetAreaToFront(pList, pArea);
  228.  
  229.       /* Bucket suchen */
  230.       pBucket = FindMarkerBucket(pArea, ulMsgID, &lFoundIndex);
  231.  
  232.       if (pBucket && lFoundIndex >=0)
  233.       {
  234.          /* Flags zuruecksetzen */
  235.          pBucket->aItems[lFoundIndex].ulFlags &= ~ulFlags;
  236.  
  237.          /* Dirty-Flags */
  238.          pArea->bDirty = TRUE;
  239.          pList->bDirty = TRUE;
  240.  
  241.          if (pBucket->aItems[lFoundIndex].ulFlags == 0)
  242.          {
  243.             /* keine Flags mehr gesetzt, Item loeschen */
  244.             pBucket->ulCountItems--;
  245.  
  246.             if (pBucket->ulCountItems)
  247.             {
  248.                /* Items uebrig, zusammenrutschen */
  249.                if (pBucket->ulCountItems != lFoundIndex)
  250.                   memmove(&(pBucket->aItems[lFoundIndex]), &(pBucket->aItems[lFoundIndex+1]), (pBucket->ulCountItems-lFoundIndex)*sizeof(MARKERITEM));
  251.             }
  252.             else
  253.             {
  254.                /* Bucket ist leer geworden, entfernen */
  255.                if (pBucket->prev)
  256.                   pBucket->prev->next = pBucket->next;
  257.                if (pBucket->next)
  258.                   pBucket->next->prev = pBucket->prev;
  259.                if (pArea->pBuckets == pBucket)
  260.                   pArea->pBuckets = pBucket->next;
  261.                free(pBucket);
  262.  
  263.                if (pArea->pBuckets == NULL)
  264.                {
  265.                   /* letztes Bucket entfernt, Area entfernen */
  266.  
  267.                   if (pArea->next)
  268.                      pArea->next->prev = pArea->prev;
  269.                   if (pArea->prev)
  270.                      pArea->prev->next = pArea->next;
  271.                   if (pList->pAreas == pArea)
  272.                      pList->pAreas = pArea->next;
  273.                   free(pArea);
  274.                }
  275.             }
  276.             DosReleaseMutexSem(pList->hmtxAccess);
  277.             return 0;
  278.          }
  279.          else
  280.          {
  281.             DosReleaseMutexSem(pList->hmtxAccess);
  282.             return 0;
  283.          }
  284.       }
  285.       else
  286.       {
  287.          DosReleaseMutexSem(pList->hmtxAccess);
  288.          return 1;
  289.       }
  290.    }
  291.    else
  292.    {
  293.       DosReleaseMutexSem(pList->hmtxAccess);
  294.       return 1;
  295.    }
  296. }
  297.  
  298. /*---------------------------------------------------------------------------*/
  299. /* Funktionsname: IsMessageMarked                                            */
  300. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  301. /* Beschreibung: Sucht eine Message in der Markierungsliste                  */
  302. /*                                                                           */
  303. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  304. /* Parameter: pList: Markierungs-Liste                                       */
  305. /*            pchAreaTag: Area-Tag                                           */
  306. /*            ulMsgID:    Message-ID                                         */
  307. /*            ulFlags:    Markierungs-Flags (MARKFLAG_*)                     */
  308. /*                                                                           */
  309. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  310. /* Rückgabewerte: TRUE   Message ist mit mindestens einem Flag markiert      */
  311. /*                FALSE  Message ist nicht markiert                          */
  312. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  313. /* Sonstiges:                                                                */
  314. /*                                                                           */
  315. /*---------------------------------------------------------------------------*/
  316.  
  317. BOOL IsMessageMarked(PMARKERLIST pList, PCHAR pchAreaTag, ULONG ulMsgID, ULONG ulFlags)
  318. {
  319.    PMARKERAREA pArea;
  320.    PMARKERBUCKET pBucket;
  321.    LONG lFoundIndex;
  322.  
  323.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  324.  
  325.    /* Area suchen */
  326.    pArea = FindMarkerArea(pList, pchAreaTag);
  327.    if (pArea)
  328.    {
  329.       /* Area nach vorne setzen */
  330.       SetAreaToFront(pList, pArea);
  331.  
  332.       /* Message in den Buckets suchen */
  333.       pBucket = FindMarkerBucket(pArea, ulMsgID, &lFoundIndex);
  334.  
  335.       if (pBucket && lFoundIndex >=0)
  336.       {
  337.          /* Flags pruefen */
  338.          if (pBucket->aItems[lFoundIndex].ulFlags & ulFlags)
  339.          {
  340.             DosReleaseMutexSem(pList->hmtxAccess);
  341.             return TRUE;
  342.          }
  343.          else
  344.          {
  345.             DosReleaseMutexSem(pList->hmtxAccess);
  346.             return FALSE;
  347.          }
  348.       }
  349.       else
  350.       {
  351.          DosReleaseMutexSem(pList->hmtxAccess);
  352.          return FALSE;
  353.       }
  354.    }
  355.    else
  356.    {
  357.       DosReleaseMutexSem(pList->hmtxAccess);
  358.       return FALSE;
  359.    }
  360. }
  361.  
  362. /*---------------------------------------------------------------------------*/
  363. /* Funktionsname: ChangeMarkedMessage                                        */
  364. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  365. /* Beschreibung: Aendert den Text einer markierten Message                   */
  366. /*                                                                           */
  367. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  368. /* Parameter: pList: Markierungs-Liste                                       */
  369. /*            pchAreaTag: Area-Tag                                           */
  370. /*            pHeader:    Neuer Header                                       */
  371. /*                                                                           */
  372. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  373. /* Rückgabewerte: 0      OK, Message geaendert                               */
  374. /*                1      Message nicht gefunden                              */
  375. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  376. /* Sonstiges:                                                                */
  377. /*                                                                           */
  378. /*---------------------------------------------------------------------------*/
  379.  
  380. int ChangeMarkedMessage(PMARKERLIST pList, PCHAR pchAreaTag, ULONG ulMsgID, MSGHEADER *pHeader)
  381. {
  382.    PMARKERAREA pArea;
  383.    PMARKERBUCKET pBucket;
  384.    LONG lFoundIndex;
  385.  
  386.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  387.  
  388.    /* Area suchen */
  389.    pArea = FindMarkerArea(pList, pchAreaTag);
  390.    if (pArea)
  391.    {
  392.       /* Area nach vorne setzen */
  393.       SetAreaToFront(pList, pArea);
  394.  
  395.       /* Message in den Buckets suchen */
  396.       pBucket = FindMarkerBucket(pArea, ulMsgID, &lFoundIndex);
  397.  
  398.       if (pBucket && lFoundIndex >=0)
  399.       {
  400.          memcpy(pBucket->aItems[lFoundIndex].pchFrom, pHeader->pchFromName, LEN_USERNAME);
  401.          memcpy(pBucket->aItems[lFoundIndex].pchSubj, pHeader->pchSubject, LEN_SUBJECT);
  402.          pArea->bDirty=TRUE;
  403.          pList->bDirty=TRUE;
  404.  
  405.          DosReleaseMutexSem(pList->hmtxAccess);
  406.          return 0;
  407.       }
  408.       else
  409.       {
  410.          DosReleaseMutexSem(pList->hmtxAccess);
  411.          return 1;
  412.       }
  413.    }
  414.    else
  415.    {
  416.       DosReleaseMutexSem(pList->hmtxAccess);
  417.       return 1;
  418.    }
  419. }
  420.  
  421. /*---------------------------------------------------------------------------*/
  422. /* Funktionsname: FindMarkerArea                                             */
  423. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  424. /* Beschreibung: Sucht eine Area in der Liste                                */
  425. /*                                                                           */
  426. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  427. /* Parameter: pList: Markierungs-Liste                                       */
  428. /*            pchAreaTag: Area-Tag                                           */
  429. /*                                                                           */
  430. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  431. /* Rückgabewerte: NULL   Area nicht gefunden                                 */
  432. /*                sonst  Zeiger auf die Area-Struktur                        */
  433. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  434. /* Sonstiges:                                                                */
  435. /*                                                                           */
  436. /*---------------------------------------------------------------------------*/
  437.  
  438. static PMARKERAREA FindMarkerArea(PMARKERLIST pList, PCHAR pchAreaTag)
  439. {
  440.    PMARKERAREA pArea=pList->pAreas;
  441.  
  442.    while (pArea && stricmp(pArea->pchAreaTag, pchAreaTag))
  443.       pArea = pArea->next;
  444.  
  445.    return pArea;
  446. }
  447.  
  448. /*---------------------------------------------------------------------------*/
  449. /* Funktionsname: FindMarkerBucket                                           */
  450. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  451. /* Beschreibung: Sucht einen Bucket in der Area                              */
  452. /*                                                                           */
  453. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  454. /* Parameter: pArea: Area                                                    */
  455. /*            ulMsgID: gesuchte Message-ID                                   */
  456. /*            plFoundIndex: Index im Array                                   */
  457. /*                                                                           */
  458. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  459. /* Rückgabewerte: NULL   Message nicht gefunden                              */
  460. /*                sonst  Zeiger auf den Bucket                               */
  461. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  462. /* Sonstiges:                                                                */
  463. /*                                                                           */
  464. /*---------------------------------------------------------------------------*/
  465.  
  466. static PMARKERBUCKET FindMarkerBucket(PMARKERAREA pArea, ULONG ulMsgID, PLONG plFoundIndex)
  467. {
  468.    PMARKERBUCKET pBucket=pArea->pBuckets;
  469.    int i=0;
  470.  
  471.    *plFoundIndex = -1;
  472.  
  473.    if (pBucket == NULL || pBucket->ulCountItems == 0)
  474.       return NULL;
  475.  
  476.    do
  477.    {
  478.       if (pBucket->aItems[0].ulMsgID <= ulMsgID &&
  479.           pBucket->aItems[pBucket->ulCountItems-1].ulMsgID >= ulMsgID)
  480.       {
  481.          /* binaere Suche */
  482.          int low=0;
  483.          int high = pBucket->ulCountItems-1;
  484.  
  485.          while(high >= low)
  486.          {
  487.             i = (low+high)/2;
  488.  
  489.             if (ulMsgID == pBucket->aItems[i].ulMsgID)
  490.             {
  491.                *plFoundIndex = i;
  492.                return pBucket;
  493.             }
  494.  
  495.             if (ulMsgID < pBucket->aItems[i].ulMsgID)
  496.                high = i-1;
  497.             else
  498.                low = i+1;
  499.          }
  500.       }
  501.       if (pBucket->next)
  502.          pBucket = pBucket->next;
  503.       else
  504.          break;
  505.    }
  506.    while(pBucket);
  507.  
  508.    return pBucket;
  509. }
  510.  
  511. /*---------------------------------------------------------------------------*/
  512. /* Funktionsname: SetAreaToFront                                             */
  513. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  514. /* Beschreibung: Setzt eine Area an den Anfang der Liste                     */
  515. /*                                                                           */
  516. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  517. /* Parameter: pList: Markierungs-Liste                                       */
  518. /*            pArea: Area                                                    */
  519. /*                                                                           */
  520. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  521. /* Rückgabewerte: 0      OK                                                  */
  522. /*                sonst  Fehler                                              */
  523. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  524. /* Sonstiges:                                                                */
  525. /*                                                                           */
  526. /*---------------------------------------------------------------------------*/
  527.  
  528. static int SetAreaToFront(PMARKERLIST pList, PMARKERAREA pArea)
  529. {
  530.    if (pArea == pList->pAreas) /* schon vorne */
  531.       return 0;
  532.    else
  533.    {
  534.       /* aushaengen */
  535.       if (pArea->next)
  536.          pArea->next->prev = pArea->prev;
  537.       if (pArea->prev)
  538.          pArea->prev->next = pArea->next;
  539.  
  540.       /* vorne einhaengen */
  541.       pArea->next = pList->pAreas;
  542.       pArea->prev = NULL;
  543.       if (pList->pAreas)
  544.          pList->pAreas->prev = pArea;
  545.       pList->pAreas = pArea;
  546.  
  547.       return 0;
  548.    }
  549. }
  550.  
  551. /*---------------------------------------------------------------------------*/
  552. /* Funktionsname: CalcAreaSize                                               */
  553. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  554. /* Beschreibung: Berechnet die Groesse aller Items in einer Area             */
  555. /*                                                                           */
  556. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  557. /* Parameter: pArea: Area                                                    */
  558. /*                                                                           */
  559. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  560. /* Rückgabewerte: Groesse der Items in Byte                                  */
  561. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  562. /* Sonstiges:                                                                */
  563. /*                                                                           */
  564. /*---------------------------------------------------------------------------*/
  565.  
  566. static ULONG CalcAreaSize(PMARKERAREA pArea)
  567. {
  568.    ULONG ulItems=0;
  569.    PMARKERBUCKET pBucket= pArea->pBuckets;
  570.  
  571.    while (pBucket)
  572.    {
  573.       ulItems += pBucket->ulCountItems;
  574.  
  575.       pBucket = pBucket->next;
  576.    }
  577.  
  578.    return ulItems * sizeof(MARKERITEM);
  579. }
  580.  
  581. /*---------------------------------------------------------------------------*/
  582. /* Funktionsname: CopyMarkerItems                                            */
  583. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  584. /* Beschreibung: Kopiert alle Items einer Area in einen Puffer               */
  585. /*                                                                           */
  586. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  587. /* Parameter: pArea: Area                                                    */
  588. /*            pDest: Zeiger auf Zielpuffer                                   */
  589. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  590. /* Rückgabewerte: 0  OK                                                      */
  591. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  592. /* Sonstiges: Puffergroesse vorher durch CalcAreaSize berechnen lassen       */
  593. /*                                                                           */
  594. /*---------------------------------------------------------------------------*/
  595.  
  596. static int CopyMarkerItems(PMARKERAREA pArea, PMARKERITEM pDest)
  597. {
  598.    ULONG ulItems=0;
  599.    PMARKERBUCKET pBucket= pArea->pBuckets;
  600.  
  601.    while (pBucket)
  602.    {
  603.       if (pBucket->ulCountItems)
  604.       {
  605.          memcpy(&(pDest[ulItems]), pBucket->aItems, pBucket->ulCountItems * sizeof(MARKERITEM));
  606.          ulItems += pBucket->ulCountItems;
  607.       }
  608.  
  609.       pBucket = pBucket->next;
  610.    }
  611.    return 0;
  612. }
  613.  
  614. /*---------------------------------------------------------------------------*/
  615. /* Funktionsname: LoadMarkerItems                                            */
  616. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  617. /* Beschreibung: Kopiert alle Items aus einem Puffer in eine Area            */
  618. /*                                                                           */
  619. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  620. /* Parameter: pArea: Area                                                    */
  621. /*            pSrc: Quellpuffer                                              */
  622. /*            ulSizeBuffer: Groesse des Puffers in Byte                      */
  623. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  624. /* Rückgabewerte: 0  OK                                                      */
  625. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  626. /* Sonstiges: Area wird als leer angenommen                                  */
  627. /*                                                                           */
  628. /*---------------------------------------------------------------------------*/
  629.  
  630. static int LoadMarkerItems(PMARKERAREA pArea, PMARKERITEM pSrc, ULONG ulSizeBuffer)
  631. {
  632.    ULONG ulBufferItems = ulSizeBuffer / sizeof(MARKERITEM);
  633.    ULONG ulItemsCopied=0;
  634.    ULONG ulItemsToCopy=0;
  635.    PMARKERBUCKET pBucket=NULL;
  636.    PMARKERBUCKET pNewBucket=NULL;
  637.  
  638.    while(ulItemsCopied < ulBufferItems)
  639.    {
  640.       /* neuen Bucket anfordern, hinten anhaengen */
  641.       pNewBucket = calloc(1, sizeof(MARKERBUCKET));
  642.  
  643.       /* einhaengen */
  644.       if (pBucket)
  645.       {
  646.          /* hinten anhaengen */
  647.          pBucket->next = pNewBucket;
  648.          pNewBucket->prev = pBucket;
  649.       }
  650.       else
  651.       {
  652.          /* erster Bucket */
  653.          pArea->pBuckets = pNewBucket;
  654.       }
  655.       pBucket = pNewBucket;
  656.  
  657.       ulItemsToCopy = (ulBufferItems - ulItemsCopied);
  658.       if (ulItemsToCopy > SIZE_BUCKET)
  659.          ulItemsToCopy = SIZE_BUCKET;
  660.  
  661.       memcpy(pBucket->aItems, &(pSrc[ulItemsCopied]), ulItemsToCopy * sizeof(MARKERITEM));
  662.       pBucket->ulCountItems = ulItemsToCopy;
  663.  
  664.       ulItemsCopied += ulItemsToCopy;
  665.    }
  666.  
  667.    return 0;
  668. }
  669.  
  670. /*---------------------------------------------------------------------------*/
  671. /* Funktionsname: ReadIniMarkers                                             */
  672. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  673. /* Beschreibung: Laedt die Markierungsliste aus einem INI-File               */
  674. /*                                                                           */
  675. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  676. /* Parameter: inifile: Handle des INI-Files                                  */
  677. /*            pList: Markierungsliste                                        */
  678. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  679. /* Rückgabewerte: 0  OK                                                      */
  680. /*                1  Fehler                                                  */
  681. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  682. /* Sonstiges: App ist "Mark", Keys sind Area-Tags                            */
  683. /*            Liste wird als leer angenommen                                 */
  684. /*---------------------------------------------------------------------------*/
  685.  
  686. int ReadIniMarkers(HINI inifile, PMARKERLIST pList)
  687. {
  688.    PMARKERAREA pArea=NULL;
  689.    PMARKERAREA pNewArea=NULL;
  690.    PCHAR pchKeys=NULL;
  691.    PCHAR pchCurrentKey=NULL;
  692.    ULONG ulKeyLen=0;
  693.    PMARKERITEM pItems=NULL;
  694.    ULONG ulBufSize=0;
  695.  
  696.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  697.    pList->bDirty = FALSE;
  698.    pList->pAreas = NULL;
  699.  
  700.    if (!inifile)
  701.    {
  702.       DosReleaseMutexSem(pList->hmtxAccess);
  703.       return 1;
  704.    }
  705.  
  706.    if (!PrfQueryProfileSize(inifile, "Mark", NULL, &ulKeyLen) || ulKeyLen == 0)
  707.    {
  708.       DosReleaseMutexSem(pList->hmtxAccess);
  709.       return 1;
  710.    }
  711.  
  712.    pchKeys=calloc(ulKeyLen+1, 1);
  713.  
  714.    if (!PrfQueryProfileData(inifile, "Mark", NULL, pchKeys, &ulKeyLen))
  715.    {
  716.       free(pchKeys);
  717.       DosReleaseMutexSem(pList->hmtxAccess);
  718.       return 1;
  719.    }
  720.  
  721.    pchCurrentKey=pchKeys;
  722.  
  723.    while (*pchCurrentKey)
  724.    {
  725.       /* neue Area anlegen */
  726.       pNewArea = calloc(1, sizeof(MARKERAREA));
  727.  
  728.       if (pArea)
  729.       {
  730.          pArea->next = pNewArea;
  731.          pNewArea->prev = pArea;
  732.       }
  733.       else
  734.       {
  735.          /* Erste Area */
  736.          pList->pAreas = pNewArea;
  737.       }
  738.       pArea = pNewArea;
  739.  
  740.       strncpy(pArea->pchAreaTag, pchCurrentKey, LEN_AREATAG);
  741.  
  742.       /* Puffer fuer die Area ermitteln */
  743.       if (PrfQueryProfileSize(inifile, "Mark", pchCurrentKey, &ulBufSize) && ulBufSize)
  744.       {
  745.          /* Puffer belegen */
  746.          pItems = malloc(ulBufSize);
  747.          if (PrfQueryProfileData(inifile, "Mark", pchCurrentKey, pItems, &ulBufSize))
  748.          {
  749.             LoadMarkerItems(pArea, pItems, ulBufSize);
  750.          }
  751.  
  752.          /* Puffer wieder freigeben */
  753.          free(pItems);
  754.       }
  755.  
  756.       while (*pchCurrentKey)
  757.          pchCurrentKey++;
  758.       pchCurrentKey++;
  759.    }
  760.    free(pchKeys);
  761.  
  762.    DosReleaseMutexSem(pList->hmtxAccess);
  763.  
  764.    return 0;
  765. }
  766.  
  767. /*---------------------------------------------------------------------------*/
  768. /* Funktionsname: SaveIniMarkers                                             */
  769. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  770. /* Beschreibung: Speichert die Markierungsliste in einem INI-File            */
  771. /*                                                                           */
  772. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  773. /* Parameter: inifile: Handle des INI-Files                                  */
  774. /*            pList: Markierungsliste                                        */
  775. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  776. /* Rückgabewerte: 0  OK                                                      */
  777. /*                1  Fehler                                                  */
  778. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  779. /* Sonstiges: App ist "Mark", Keys sind Area-Tags                            */
  780. /*                                                                           */
  781. /*---------------------------------------------------------------------------*/
  782.  
  783. int SaveIniMarkers(HINI inifile, PMARKERLIST pList)
  784. {
  785.    PMARKERAREA pArea=NULL;
  786.    PMARKERITEM pItems=NULL;
  787.    ULONG ulItemSize=0;
  788.    PCHAR pchCurrentKey=NULL;
  789.    PCHAR pchKeys=NULL;
  790.    ULONG ulKeyLen=0;
  791.  
  792.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  793.  
  794.    pArea=pList->pAreas;
  795.  
  796.    if (!inifile)
  797.    {
  798.       DosReleaseMutexSem(pList->hmtxAccess);
  799.       return 1;
  800.    }
  801.  
  802.    /* Areas speichern */
  803.    while(pArea)
  804.    {
  805.       if (pArea->bDirty)
  806.       {
  807.          ulItemSize = CalcAreaSize(pArea);
  808.          pItems = malloc(ulItemSize);
  809.          CopyMarkerItems(pArea, pItems);
  810.          PrfWriteProfileData(inifile, "Mark", pArea->pchAreaTag, pItems, ulItemSize);
  811.          free(pItems);
  812.  
  813.          pArea->bDirty = FALSE;
  814.       }
  815.       pArea = pArea->next;
  816.    }
  817.    pList->bDirty = FALSE;
  818.  
  819.    /* geloeschte Areas pruefen */
  820.    if (!PrfQueryProfileSize(inifile, "Mark", NULL, &ulKeyLen) || ulKeyLen == 0)
  821.    {
  822.       DosReleaseMutexSem(pList->hmtxAccess);
  823.       return 1;
  824.    }
  825.  
  826.    pchKeys=calloc(ulKeyLen+1, 1);
  827.  
  828.    if (!PrfQueryProfileData(inifile, "Mark", NULL, pchKeys, &ulKeyLen))
  829.    {
  830.       free(pchKeys);
  831.       DosReleaseMutexSem(pList->hmtxAccess);
  832.       return 1;
  833.    }
  834.  
  835.    pchCurrentKey=pchKeys;
  836.  
  837.    while (*pchCurrentKey)
  838.    {
  839.       /* Case-sensitiv vergleichen */
  840.       pArea = pList->pAreas;
  841.       while (pArea && strcmp(pArea->pchAreaTag, pchCurrentKey))
  842.          pArea = pArea->next;
  843.  
  844.       if (!pArea) /* alte Area loeschen */
  845.          PrfWriteProfileData(inifile, "Mark", pchCurrentKey, NULL, 0);
  846.  
  847.       while (*pchCurrentKey)
  848.          pchCurrentKey++;
  849.       pchCurrentKey++;
  850.    }
  851.    free(pchKeys);
  852.  
  853.    DosReleaseMutexSem(pList->hmtxAccess);
  854.  
  855.    return 0;
  856. }
  857.  
  858. /*---------------------------------------------------------------------------*/
  859. /* Funktionsname: OpenMarkerList                                             */
  860. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  861. /* Beschreibung: Bereitet die Liste zur Verwendung vor                       */
  862. /*                                                                           */
  863. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  864. /* Parameter: pList: Markierungsliste                                        */
  865. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  866. /* Rückgabewerte: 0  OK                                                      */
  867. /*                1  Fehler                                                  */
  868. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  869. /* Sonstiges:                                                                */
  870. /*                                                                           */
  871. /*---------------------------------------------------------------------------*/
  872.  
  873. int OpenMarkerList(PMARKERLIST pList)
  874. {
  875.    if (DosCreateMutexSem(NULL, &pList->hmtxAccess, 0, FALSE))
  876.       return 1;
  877.    else
  878.       return 0;
  879. }
  880.  
  881. /*---------------------------------------------------------------------------*/
  882. /* Funktionsname: CloseMarkerList                                            */
  883. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  884. /* Beschreibung: Beendet den Zugriff auf die Markerliste                     */
  885. /*                                                                           */
  886. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  887. /* Parameter: pList: Markierungsliste                                        */
  888. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  889. /* Rückgabewerte: 0  OK                                                      */
  890. /*                1  Fehler                                                  */
  891. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  892. /* Sonstiges:                                                                */
  893. /*                                                                           */
  894. /*---------------------------------------------------------------------------*/
  895.  
  896. int CloseMarkerList(PMARKERLIST pList)
  897. {
  898.    if (DosCloseMutexSem(pList->hmtxAccess))
  899.       return 1;
  900.    else
  901.       return 0;
  902. }
  903.  
  904. /*---------------------------------------------------------------------------*/
  905. /* Funktionsname: CheckMarkerAreas                                           */
  906. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  907. /* Beschreibung: Prueft, ob noch alle Areas in den Markierungen vorhanden    */
  908. /*               sind, loescht ggf. die Area                                 */
  909. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  910. /* Parameter: pList: Markierungsliste                                        */
  911. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  912. /* Rückgabewerte: 0  OK                                                      */
  913. /*                1  Fehler                                                  */
  914. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  915. /* Sonstiges:                                                                */
  916. /*                                                                           */
  917. /*---------------------------------------------------------------------------*/
  918.  
  919. int CheckMarkerAreas(PMARKERLIST pList)
  920. {
  921.    extern AREALIST arealiste;
  922.    PMARKERAREA pArea=NULL;
  923.  
  924.    WinRequestMutexSem(pList->hmtxAccess, SEM_INDEFINITE_WAIT);
  925.  
  926.    pArea=pList->pAreas;
  927.    while (pArea)
  928.    {
  929.       if (AM_FindArea(&arealiste, pArea->pchAreaTag))
  930.          pArea=pArea->next; /* OK, weiter */
  931.       else
  932.       {
  933.          /* Area existiert nicht mehr, loeschen */
  934.          PMARKERBUCKET pBucket, pBucket2;
  935.          PMARKERAREA pArea2;
  936.  
  937.          pBucket=pArea->pBuckets;
  938.          while (pBucket)
  939.          {
  940.             pBucket2=pBucket;
  941.             pBucket=pBucket->next;
  942.             free(pBucket2);
  943.          }
  944.          pArea2=pArea;
  945.          if (pArea->next)
  946.             pArea->next->prev = pArea->prev;
  947.          if (pArea->prev)
  948.             pArea->prev->next = pArea->next;
  949.          if (pList->pAreas == pArea)
  950.             pList->pAreas = pArea->next;
  951.          pArea=pArea->next;
  952.          free(pArea2);
  953.          pList->bDirty=TRUE;
  954.       }
  955.    }
  956.  
  957.    DosReleaseMutexSem(pList->hmtxAccess);
  958.  
  959.    return 0;
  960. }
  961. /*-------------------------------- Modulende --------------------------------*/
  962.  
  963.