home *** CD-ROM | disk | FTP | other *** search
/ PC Musician 2000 / PC_Musician_2000.iso / PCMUSIC / NOTATION / SCOREIO / SCLIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-26  |  25.4 KB  |  565 lines

  1. /*---------------------- SCORE.LIB Library to read and write SCORE files -----*/
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <malloc.h>
  6. #include "sctypes.h"
  7. #include "sclib.h"
  8.  
  9. /*----------------------------------------------------------------------------*/
  10. /* get_fnames   Dieser Funktion wird ein String-Feld übergeben. Der Eintrag   */
  11. /*              0 wird auf Vorhandensein geprüft und dann maximal count       */
  12. /*              weitere lexikographische Einträge gesucht und damit die       */
  13. /*              weiteren Felder gefüllt.                                      */
  14. /*                                                                            */
  15. /*              Rückgabe:         > 0: Entprechend viele Dateien gefunden     */
  16. /*                                = 0: Datei konnte nicht gefunden werden     */
  17. /*                                < 0: Ungültiger Dateiname übergeben.        */
  18. /*                                                                            */
  19. /*----------------------------------------------------------------------------*/
  20. /* get_fnames   This Funktion receives a stringarray. The first entry         */
  21. /*              (fname[0]) must contain a filename. The function searches     */
  22. /*              'count' more filenames in alphabetical order and fills the    */
  23. /*              stringarray with filenames                                    */
  24. /*                                                                            */
  25. /*              Return:           > 0: number of files found                  */
  26. /*                                = 0: no files found                         */
  27. /*                                < 0: illegal filename                       */
  28. /*                                                                            */
  29. /*----------------------------------------------------------------------------*/
  30. Int     get_fnames(Char fname[][FNAME_LEN], Int count, Int name_max)
  31. {
  32.         Int             i,erg1,erg2,pos;
  33.         Char            *s1, c;
  34.  
  35.         s1  = strpbrk(fname[0],".");
  36.         if (s1  == NULL) return(-1);
  37.         pos =(Int) (s1 - fname[0] - 1);
  38.  
  39.         if (count > name_max) count = name_max;
  40.  
  41.         for (i = 0; i < count; i++) {
  42.           erg1 = exists(fname[i]);
  43.           if ((erg1 == 0) && (i == 0)) return(0);
  44.           if ((erg1 != 0) && (pos < 1)) return(i);
  45.           if (erg1 == 0) {
  46.             c = fname[i][pos];
  47.             if ((c > 47) && (c < 59))
  48.               fname[i][pos] = 48;
  49.             else
  50.               fname[i][pos] = 65;
  51.             fname[i][pos-1] += 1;
  52.             erg2 = exists(fname[i]);
  53.             if ((erg2 == 0) && (pos < 2)) return(i);
  54.             if (erg2 == 0) {
  55.               c = fname[i][pos-1];
  56.               if ((c > 47) && (c < 59))
  57.                 fname[i][pos-1] = 48;
  58.               else
  59.                 fname[i][pos-1] = 65;
  60.               fname[i][pos-2] += 1;
  61.               if (exists(fname[i]) == 0) return(i);
  62.             }
  63.           }
  64.           strcpy(fname[i+1],fname[i]);
  65.           fname[i+1][pos] += 1;
  66.         }
  67.         return(i);
  68.  
  69. }
  70.  
  71. /*----------------------------------------------------------------------------*/
  72. /*  exists      Diese Funktion überprüft, ob der übergebene Dateiname         */
  73. /*              vorhanden ist.                                                */
  74. /*              Rückgabewert 0: Datei wurde nicht gefunden                    */
  75. /*                           1: Datei wurde gefunden                          */
  76. /*----------------------------------------------------------------------------*/
  77. /*  exists      This function checks whether the filenam exists               */
  78. /*                                                                            */
  79. /*              Return:      0: file found                                    */
  80. /*                           1: file not found                                */
  81. /*----------------------------------------------------------------------------*/
  82. Int exists(Char *filename)
  83. {
  84.         FILE *f_handler;
  85.  
  86.         f_handler = fopen(filename, "rb");
  87.         if (f_handler == NULL) return(0);
  88.  
  89.         fclose(f_handler);
  90.         return(1);
  91. }
  92.  
  93. /*----------------------------------------------------------------------------*/
  94. /* get_parms  Diese Funktion liest eine SCORE-Datei in eine verkettete        */
  95. /*            Listenstruktur ein (siehe SCORE.H). Dazu wird ein Listen-       */
  96. /*            kopf übergeben der Zeiger auf das erste und letzte Listen-      */
  97. /*            element enthält, die aber noch uninitialisiert sind. Ausser-    */
  98. /*            dem enthält der Listenkopf noch Informationen über die          */
  99. /*            Gesamtzahl der Parameter und Objekte und die fünf letzten       */
  100. /*            Parameter die keinem Objekt zugeordnet sind und nach meiner     */
  101. /*            Erfahrung immer 0.0, 3.0, 1.0, 4.0, -9999.0 enthalten.          */
  102. /*            Bei der Datenstruktur handelt es sich um eine zweifach          */
  103. /*            verkettete Liste mit einem Datenfeld für 19 Fließkommazahlen    */
  104. /*            und einem Zeiger auf Text der nur bei Objekten vom Typ          */
  105. /*            Text (16) und EPS (15) verwendet wird. Der erste Eintrag        */
  106. /*            im Zahlenfeld (cd[0]) enthält die Anzahl der gültigen           */
  107. /*            Parameter also maximal 18. Ausnahmen stellen Objekte vom        */
  108. /*            Typ 15 und 16 dar. Hier sind genau 13 Parameter gültig.         */
  109. /*                                                                            */
  110. /* Rückgabe:   OK            SCORE-Datei erfolgreich eingelesen               */
  111. /*            CONSIST_ERR   Konsistenzfehler in der internen Datenstruktur    */
  112. /*            FORMAT_ERR    Formatfehler in der SCORE-Datei                   */
  113. /*            MEMORY_ERR    Fehler bei der Speicherreservierung               */
  114. /*            FILE_ERR      Fehler beim Öffnen der Datei                      */
  115. /*                                                                            */
  116. /*----------------------------------------------------------------------------*/
  117. /* get_parms  This function reads a SCORE file in a double linked list        */
  118. /*            (see SCORE.H) The function needs a listhead which contains      */
  119. /*            uninitialized pointers to the first and last listitem.          */
  120. /*            Additionaly the listhead contains information about the total   */
  121. /*            number of parameters and items and the 5 last parameters        */
  122. /*            which are not assigned to a specific item and always contain    */
  123. /*            0.0, 3.0, 1.0, 4.0, -9999.0. The objects of the double-linked-  */
  124. /*            list contain the data of the SCORE-items in an array of         */
  125. /*            19 floatnumbers and a pointer to char which is only used for    */
  126. /*            code 16 (Text) and code-15 (EPS) items.                         */
  127. /*            The first entry in the float-array cd[0] contains the number    */
  128. /*            of valid entries.                                               */
  129. /*                                                                            */
  130. /*            ATTENTION !!! If you modify a score item do not forget to       */
  131. /*            update cd[0] if the number of valid parameters has changed.     */
  132. /*                                                                            */
  133. /* Return:    OK            SCORE-file sucessfully processed                  */
  134. /*            CONSIST_ERR   Consistency error in the internal datastructure   */
  135. /*            FORMAT_ERR    Format error in the SCORE file                    */
  136. /*            MEMORY_ERR    Error while allocating memory                     */
  137. /*            FILE_ERR      Error hen trying to open a file                   */
  138. /*                                                                            */
  139. /*----------------------------------------------------------------------------*/
  140. Int     get_parms(Char *fname, list_ptr sl)
  141. {
  142.         FILE    *handle;
  143.         Int     count, tmp_cnt, parm_cnt;
  144.         Int     rd_stat, i, fsize, item_type;
  145.         Float   fl_num;
  146.         item_ptr cur_pos, temp;
  147.  
  148.         count    =   0;
  149.         parm_cnt =   0;
  150.  
  151.         handle = fopen(fname, "rb");                   /* Datei öffnen */
  152.         if (handle == NULL) return(FILE_ERR);
  153.  
  154.         rd_stat = fread(&fsize, 2, 1, handle);         /* Parameter Anzahl  */
  155.         if (rd_stat != 1)  {fclose(handle); return(FORMAT_ERR);}
  156.  
  157.  
  158.         while (count < fsize - 7) {                     /* Parameter einlesen */
  159.  
  160.           if (count == 0) {
  161.             temp = (item_ptr) malloc(sizeof(item));
  162.             if (temp == NULL) { fclose(handle); return(MEMORY_ERR);}
  163.  
  164.             sl -> first = temp;
  165.             sl -> last  = temp;
  166.             cur_pos     = temp;
  167.  
  168.             cur_pos -> text = NULL;
  169.             cur_pos -> tied = NULL;
  170.             cur_pos -> next = NULL;
  171.             cur_pos -> prev = NULL;
  172.           }
  173.           else {
  174.             temp = (item_ptr) malloc(sizeof(item));
  175.             if (temp == NULL) { fclose(handle); return(MEMORY_ERR);}
  176.  
  177.             cur_pos -> next = temp;
  178.             sl      -> last = temp;
  179.  
  180.             temp    -> text = NULL;
  181.             temp    -> tied = NULL;
  182.             temp    -> next = NULL;
  183.             temp    -> prev = cur_pos;
  184.             cur_pos         = temp;
  185.           }                               /* cur_pos zeigt nun auf neues Item */
  186.  
  187.  
  188.           rd_stat = fread(&fl_num, 4, 1, handle);           /* Länge des Item */
  189.           if (rd_stat != 1)  {fclose(handle);return(FORMAT_ERR);}
  190.           if (fl_num < 2.0F) {fclose(handle);return(FORMAT_ERR);}
  191.           count += 1;
  192.           cur_pos -> cd[0] =       fl_num;
  193.           parm_cnt         = (Int) fl_num;
  194.           if (fabs(fl_num - (Float) parm_cnt) > FLOAT_EPS) {
  195.             fclose(handle);return(FORMAT_ERR);
  196.           }
  197.  
  198.           rd_stat = fread(&fl_num, 4, 1, handle);                /* Objekttyp */
  199.           if (rd_stat != 1)  {fclose(handle);return(FORMAT_ERR);}
  200.           count += 1;
  201.           cur_pos -> cd[1] =       fl_num;
  202.           item_type        = (Int) fl_num;
  203.  
  204.           if ((item_type == 15) || (item_type == 16)) {      /* EPS oder Text */
  205.             if (parm_cnt < 14)  {fclose(handle);return(FORMAT_ERR);}
  206.  
  207.             for (i = 2; i <= 13; i++) {
  208.               rd_stat = fread(&fl_num, 4, 1, handle);          /* Param. rest */
  209.               if (rd_stat != 1)  {fclose(handle);return(FORMAT_ERR);}
  210.               count += 1;
  211.               cur_pos -> cd[i] = fl_num;
  212.             }
  213.             tmp_cnt = parm_cnt - 13;                  /* Größe des Text div 4 */
  214.             cur_pos -> text = (string) malloc(4 * tmp_cnt);
  215.             if (cur_pos -> text == NULL) {fclose(handle); return(MEMORY_ERR);}
  216.  
  217.             rd_stat = fread(cur_pos -> text, 4, tmp_cnt, handle);
  218.             if (rd_stat != tmp_cnt)  {fclose(handle);return(FORMAT_ERR);}
  219.             count += tmp_cnt;
  220.           }
  221.           else {
  222.             for (i = 2; i <= parm_cnt; i++) {
  223.               rd_stat = fread(&fl_num, 4, 1, handle);          /* Param. rest */
  224.               if (rd_stat != 1)  {fclose(handle);return(FORMAT_ERR);}
  225.               count += 1;
  226.               cur_pos -> cd[i] = fl_num;
  227.             }
  228.             for (i = parm_cnt+1; i < MAX_CD; i++) cur_pos->cd[i] = 0.0F;
  229.           }                   /* alle Parameter eines Item wurden eingetragen */
  230.         }                                     /* end while (count < fsize-5)  */
  231.  
  232.         parm_cnt = fsize - count;
  233.         rd_stat = fread(sl->cd, 4, parm_cnt, handle);
  234.         if ((rd_stat != parm_cnt) || (sl->cd[parm_cnt-1] != -9999.0F)) {
  235.           fclose(handle);
  236.           return(FORMAT_ERR);
  237.         }
  238.  
  239.         fclose(handle);
  240.         sl->trail_len = parm_cnt;
  241.         if (set_info(sl) != OK) return(CONSIST_ERR);
  242.         return(OK);
  243. }
  244.  
  245. /*----------------------------------------------------------------------------*/
  246. /* put_parms    Diese Funktion schreibt die Datenstruktur nach                */
  247. /*              SCORE-Konventionen in eine Datei.                             */
  248. /*                                                                            */
  249. /* Rückgabe:    OK              Datei wurde erfolgreich geschrieben           */
  250. /*              FILE_ERR        Datei nicht gefunden oder Diskette voll       */
  251. /*              CONSIST_ERR     Fehler in Listenstruktur                      */
  252. /*----------------------------------------------------------------------------*/
  253. /* put_parms    This Function writes the SCORE-list according to the          */
  254. /*              SCORE-binary format in a file.                                */
  255. /*                                                                            */
  256. /* Return:      OK              File sucessfully saved                        */
  257. /*              FILE_ERR        No more space available on disk               */
  258. /*              CONSIST_ERR     error in the liststructure                    */
  259. /*----------------------------------------------------------------------------*/
  260. Int     put_parms(Char *fname, list_ptr sl)
  261. {
  262.         FILE       *handle;
  263.         Int        parm_cnt, fsize, wr_stat, tmp_cnt;
  264.         item_ptr   cur_pos;
  265.  
  266.         handle = fopen(fname, "wb");
  267.         if (handle == NULL)     return(FILE_ERR);
  268.         if (set_info(sl) != OK) return(CONSIST_ERR);
  269.  
  270.         fsize = sl -> parameters + sl -> trail_len;
  271.         wr_stat = fwrite(&fsize, 2, 1, handle);
  272.         if (wr_stat != 1) {fclose(handle); return(FILE_ERR);}
  273.  
  274.         cur_pos = sl -> first;
  275.         while (cur_pos != NULL) {
  276.  
  277.           parm_cnt = (Int) cur_pos -> cd[0];
  278.  
  279.           if ((cur_pos->cd[1] == 15.0F)||(cur_pos->cd[1] == 16.0F)) {
  280.  
  281.             wr_stat = fwrite(cur_pos->cd, 4, 14, handle);
  282.             if (wr_stat != 14) {fclose(handle); return(FILE_ERR);}
  283.  
  284.             tmp_cnt = parm_cnt - 13;
  285.             if (tmp_cnt < 1) {fclose(handle); return(FORMAT_ERR);}
  286.  
  287.             wr_stat = fwrite(cur_pos->text, 4, tmp_cnt, handle);
  288.             if (wr_stat != tmp_cnt) {fclose(handle); return(FILE_ERR);}
  289.           }
  290.           else {
  291.             wr_stat = fwrite(cur_pos->cd, 4, parm_cnt+1, handle);
  292.             if (wr_stat != parm_cnt+1) {fclose(handle); return(FILE_ERR);}
  293.           }
  294.  
  295.           cur_pos = cur_pos -> next;
  296.         }                                      /* end of while (cur_pos) != 0 */
  297.  
  298.         wr_stat = fwrite(sl->cd, 4, sl->trail_len, handle);
  299.         if (wr_stat != sl->trail_len) {fclose(handle); return(FILE_ERR);}
  300.  
  301.         fclose(handle);
  302.         return(OK);
  303. }
  304.  
  305. /*----------------------------------------------------------------------------*/
  306. /* set_free     Diese Hilfsfunktion gibt mit Hilfe der free()-Funktion        */
  307. /*              den gsamten allozierten Speicher der Datenstruktur wieder     */
  308. /*              frei. Alle Daten gehen verloren                               */
  309. /*              Die Datenstruktur score_item enthält auch einen Zeiger auf    */
  310. /*              ein Textfeld der normalerweise auf NULL zeigt. Wenn dieser    */
  311. /*              Zeiger auf einen Textbereich zeigt wird dieser Speicher       */
  312. /*              nicht freigegeben.                                            */
  313. /*----------------------------------------------------------------------------*/
  314. /* set_free     This function uses the free()-function to release the         */
  315. /*              allocated memeory used by the SCORE-itemlist. All data will   */
  316. /*              be lost.                                                      */
  317. /*              Allocated memory used for Textdata in code 15 and code 16 -   */
  318. /*              items is not released in this version of the software.        */
  319. /*----------------------------------------------------------------------------*/
  320. void    set_free(list_ptr sl)
  321. {
  322.         item_ptr   cur_pos, temp;
  323.  
  324.  
  325.         cur_pos = sl -> last;
  326.  
  327.         while (cur_pos != NULL) {
  328.           temp = cur_pos -> prev;
  329.           free(cur_pos);
  330.           cur_pos = temp;
  331.         }
  332.  
  333. }
  334.  
  335. /*----------------------------------------------------------------------------*/
  336. /* set_info     Diese Hilfsfunktion ermittelt folgende Werte:                 */
  337. /*              sl -> items           = Anzahl vorhandener Objekte            */
  338. /*              sl -> parameters      = Anzahl aller Parameter                */
  339. /*              Ausserdem wird die Konsistenz der Liste überprüft             */
  340. /*              Rückgabe: OK                                                  */
  341. /*                        CONSIST_ERR                                         */
  342. /*----------------------------------------------------------------------------*/
  343. /* set_info     This Function calculates the following figures:               */
  344. /*              sl -> items           = number of items                       */
  345. /*              sl -> parameters      = total number of parameters            */
  346. /*              additionally the list-consistency will be checked             */
  347. /*              Return:   OK                                                  */
  348. /*                        CONSIST_ERR                                         */
  349. /*----------------------------------------------------------------------------*/
  350. Int     set_info(list_ptr sl)
  351. {
  352.         Int        item_cnt, parm_cnt;
  353.         item_ptr   cur_pos, temp;
  354.  
  355.         item_cnt  = 0;
  356.         parm_cnt  = 0;
  357.  
  358.         cur_pos = sl -> first;
  359.         if (cur_pos == NULL)         return(CONSIST_ERR);
  360.         if (cur_pos -> prev != NULL) return(CONSIST_ERR);
  361.  
  362.         while (cur_pos -> next != NULL) {
  363.           temp       = cur_pos -> next;
  364.           if (temp -> prev != cur_pos) return(CONSIST_ERR);
  365.           item_cnt  += 1;
  366.           parm_cnt  += (Int) cur_pos -> cd[0] + 1;
  367.           cur_pos    = temp;
  368.         }
  369.  
  370.         if (cur_pos != sl -> last) return(CONSIST_ERR);
  371.         item_cnt  += 1;
  372.         parm_cnt  += (Int) cur_pos -> cd[0] + 1;
  373.  
  374.         sl -> items      = item_cnt;
  375.         sl -> parameters = parm_cnt;
  376.         return(OK);
  377. }
  378.  
  379. /*----------------------------------------------------------------------------*/
  380. /*   Diese Funktion sortiert alle Objekte nach ihrem X-Wert (cd[3])           */
  381. /*   Die Sortiermethode berücksichtigt, daß eine SCORE-Datei normalerweise    */
  382. /*   bereits aus sortierten Teilstücken besteht und stellt für diesen         */
  383. /*   Fall die schnellste Implementation dar.                                  */
  384. /*                                                                            */
  385. /*   Rückgabewert: OK                                                         */
  386. /*                 CONSIST_ERR   (Listenstruktur beschädigt)                  */
  387. /*                                                                            */
  388. /*----------------------------------------------------------------------------*/
  389. /*   This function sorts all items according to the x-value (cd[3]).          */
  390. /*   The sorting method takes into account that normaly a SCORE-file          */
  391. /*   contains already sorted strings of items and is therefore an             */
  392. /*   performance optimized implementation.                                    */
  393. /*                                                                            */
  394. /*   Return:       OK                                                         */
  395. /*                 CONSIST_ERR   (liststructure damaged)                      */
  396. /*                                                                            */
  397. /*----------------------------------------------------------------------------*/
  398. Int     sort_items_x(list_ptr head)
  399. {
  400.         struct score_item cliplow, cliphigh;
  401.         struct score_item  *z1, *z2;
  402.         Bool  z1_ge_z2, z1_le_z2next;
  403.  
  404. /*------------------- Initializing ------------------------------*/
  405.  
  406.         cliplow.next  = &cliphigh;
  407.         cliplow.prev  = NULL;
  408.  
  409.         cliphigh.next = NULL;
  410.         cliphigh.prev = &cliplow;
  411.  
  412.         cliplow.cd[3]  = -1E38;
  413.         cliphigh.cd[3] = 1E38 ;
  414.  
  415.         z1 = head->first;
  416.         z2 = &cliplow;
  417.  
  418. /*---------------------------------------------------------------*/
  419. /* Sortierung: Die Liste wird nun Stück für Stück zwischen       */
  420. /*             cliplow und cliphigh einsortiert                  */
  421. /*---------------------------------------------------------------*/
  422. /* Sort:       The items will be inserted in sorted order        */
  423. /*             between cliplow and cliphigh.                     */
  424. /*---------------------------------------------------------------*/
  425.         while (head->first != NULL) {
  426.  
  427.           if (z1->cd[3] >= z2->cd[3]) z1_ge_z2 = TRUE;
  428.           else                        z1_ge_z2 = FALSE;
  429.  
  430.           if (z1->cd[3] < z2->next->cd[3]) z1_le_z2next = TRUE;
  431.           else                             z1_le_z2next = FALSE;
  432.  
  433.           if (z1_ge_z2 && z1_le_z2next) {
  434.  
  435.             head->first  = z1->next;
  436.  
  437.             z1->next       = z2->next;
  438.             z2->next->prev = z1;
  439.             z2->next       = z1;
  440.             z1->prev       = z2;
  441.  
  442.             z2 = z1;
  443.             z1 = head->first;
  444.           }
  445.           else {
  446.             if (z1_ge_z2) {
  447.               z2 = z2->next;
  448.             }
  449.             else {
  450.               z2 = &cliplow;
  451.             }
  452.           }
  453.         }
  454.  
  455. /*---------------------------------------------------------------*/
  456. /* Nachlauf: die sortierte Liste wird nun an head angehängt      */
  457. /*                                                               */
  458. /*---------------------------------------------------------------*/
  459. /* Finish:   the sorted list is now moved back to head           */
  460. /*                                                               */
  461. /*---------------------------------------------------------------*/
  462.         head->first = cliplow.next;
  463.         head->last  = cliphigh.prev;
  464.  
  465.         head->first->prev = NULL;
  466.         head->last->next  = NULL;
  467.  
  468.         return(set_info(head));  /* Konsistenzprüfung */
  469. }
  470.  
  471. /*----------------------------------------------------------------------------*/
  472. /* sort_items_xy Diese Sortierfunktion entspricht dem OS-Befehl in SCORE      */
  473. /*                                                                            */
  474. /*   Die Sortiermethode berücksichtigt, daß eine SCORE-Datei normalerweise    */
  475. /*   bereits aus sortierten Teilstücken besteht und stellt für diesen         */
  476. /*   Fall die schnellste Implementation dar.                                  */
  477. /*                                                                            */
  478. /*               Rückgabe: OK                                                 */
  479. /*                         CONSIST_ERR                                        */
  480. /*----------------------------------------------------------------------------*/
  481. /* sort_items_xy This Function is realizes the OS Command in SCORE            */
  482. /*                                                                            */
  483. /*   The sorting method takes into account that normaly a SCORE-file          */
  484. /*   contains already sorted strings of items and is therefore an             */
  485. /*   performance optimized implementation.                                    */
  486. /*                                                                            */
  487. /*               Return:   OK                                                 */
  488. /*                         CONSIST_ERR                                        */
  489. /*----------------------------------------------------------------------------*/
  490. Int     sort_items_xy(list_ptr head)
  491. {
  492.         struct score_item cliplow, cliphigh;
  493.         struct score_item  *z1, *z2;
  494.         Bool  z1_ge_z2, z1_le_z2next;
  495.  
  496. /*------------------- Initializing ------------------------------*/
  497.  
  498.         cliplow.next  = &cliphigh;
  499.         cliplow.prev  = NULL;
  500.         cliphigh.next = NULL;
  501.         cliphigh.prev = &cliplow;
  502.  
  503.         cliplow.cd[3]  = -1E38;
  504.         cliplow.cd[2]  = -32768.0F;
  505.         cliphigh.cd[3] = 1E38 ;
  506.         cliphigh.cd[2] = 32767.0F;
  507.  
  508.         z1 = head->first;
  509.         z2 = &cliplow;
  510.  
  511. /*------------------- Sort --------------------------------------*/
  512.  
  513.         while (head->first != NULL) {
  514.  
  515.           if ( (Int) z1->cd[2] > (Int) z2->cd[2])
  516.               z1_ge_z2 = TRUE;
  517.           else if (( (Int) z1->cd[2] == (Int) z2->cd[2])
  518.                 && (z1->cd[3] >= z2->cd[3]))
  519.               z1_ge_z2 = TRUE;
  520.           else
  521.               z1_ge_z2 = FALSE;
  522.  
  523.           if ( (Int) z1->cd[2] < (Int) z2->next->cd[2])
  524.               z1_le_z2next = TRUE;
  525.           else if (( (Int) z1->cd[2] == (Int) z2->next->cd[2])
  526.                 && (z1->cd[3] < z2->next->cd[3]))
  527.               z1_le_z2next = TRUE;
  528.           else
  529.               z1_le_z2next = FALSE;
  530.  
  531.  
  532.           if (z1_ge_z2 && z1_le_z2next) {
  533.  
  534.             head->first  = z1->next;
  535.  
  536.             z1->next       = z2->next;
  537.             z2->next->prev = z1;
  538.             z2->next       = z1;
  539.             z1->prev       = z2;
  540.  
  541.             z2 = z1;
  542.             z1 = head->first;
  543.           }
  544.           else {
  545.             if (z1_ge_z2) {
  546.               z2 = z2->next;
  547.             }
  548.             else {
  549.               z2 = &cliplow;
  550.             }
  551.           }
  552.         }
  553.  
  554. /*------------------- Finish ------------------------------------*/
  555.  
  556.         head->first = cliplow.next;
  557.         head->last  = cliphigh.prev;
  558.  
  559.         head->first->prev = NULL;
  560.         head->last->next  = NULL;
  561.  
  562.         return(set_info(head));  /* Konsistenzprüfung */
  563. }
  564.  
  565.