1 /*
2 cmap_labels.c: read and write map header labels
3 Copyright (C) 2001 CCLRC, Charles Ballard
4
5 This library is free software: you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 version 3, modified in accordance with the provisions of the
8 license to address the requirements of UK law.
9
10 You should have received a copy of the modified GNU Lesser General
11 Public License along with this library. If not, copies may be
12 downloaded from http://www.ccp4.ac.uk/ccp4license.php
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18 */
19 #include <string.h>
20 #include "cmaplib.h"
21 #include "cmap_labels.h"
22 #include "cmap_errno.h"
23
24 /*! Internal: read the labels from file header and copy into char * array
25 Called when the file is opened in read mode.
26 \param mfile (CMMFile *)
27 \return 1 on succes */
parse_maplabels(CMMFile * mfile)28 int parse_maplabels(CMMFile *mfile)
29 {
30 char buffer[81], *cptr;
31 const unsigned int n_byt_label = 80U, max_label = 10U;
32 /* const unsigned int labels_offset = 224U; */
33 int i;
34
35 /* ccp4_file_seek(mfile->stream,labels_offset,SEEK_SET); */
36 for (i=0 ; i!=mfile->labels.number ; i++) {
37 ccp4_file_readchar(mfile->stream,(uint8 *) buffer,n_byt_label);
38 cptr = buffer+n_byt_label;
39 while (cptr> buffer && *--cptr == ' ');
40 *(++cptr) = '\0';
41 mfile->labels.labels[i] = strdup(buffer);
42 }
43 ccp4_file_raw_seek(mfile->stream,(max_label-mfile->labels.number)
44 *n_byt_label,
45 SEEK_CUR);
46 return 1;
47 }
48
49 /*! Internal: dump the labels char * array to file, offset at 224 bytes.
50 Called when the file is opened or closed in write mode, immediately after the
51 header is written.
52 \param mfile (const CMMFile *)
53 \return 1 on success, 0 on failure */
write_maplabels(const CMMFile * mfile)54 int write_maplabels(const CMMFile *mfile)
55 {
56 char buffer[80];
57 /* const unsigned int labels_offset = 224U; */
58 int i, result = 0;
59 size_t slen;
60
61 /* ccp4_file_seek(mfile->stream,labels_offset,SEEK_SET); */
62 for (i=0 ; i != mfile->labels.number ; i++) {
63 memset(buffer,' ',80U);
64 slen = strlen(mfile->labels.labels[i]);
65 if (slen > 80U) slen = 80U;
66 strncpy(buffer,mfile->labels.labels[i],slen);
67 result += ccp4_file_writechar(mfile->stream,(uint8 *) buffer,80U);
68 }
69 memset(buffer,' ',80U);
70 while(i != 10) {
71 result += ccp4_file_writechar(mfile->stream,(uint8 *) buffer,80U);
72 i++;
73 }
74 return (result == 800) ? 1 : 0 ;
75 }
76
77 /*! Set the label in the map header. Headers are 80 characters long.
78 The labels are written to the file when it is closed. Therefore,
79 the file must be in write mode.
80 If label == NULL the element corresponding to posn is removed.
81 The number of labels is recalculated on each call.
82 \param mfile (CMMFile *)
83 \param label (const char *) the C-style character array
84 \param posn (int) the label number (C-style, 0 -> 9)
85 \return number of label effected, or EOF */
ccp4_cmap_set_label(CMMFile * mfile,const char * label,int posn)86 int ccp4_cmap_set_label(CMMFile *mfile, const char *label, int posn)
87 {
88 int i,j;
89
90 if (mfile == NULL) {
91 ccp4_signal( CCP4_ERRLEVEL(3) | CMAP_ERRNO(CMERR_NoChannel),
92 "ccp4_cmap_set_label",NULL);
93 return (EOF);}
94
95 if (ccp4_file_is_write(mfile->stream) == 0) {
96 ccp4_signal( CCP4_ERRLEVEL(3) | CMAP_ERRNO(CMERR_WriteFail),
97 "ccp4_cmap_label_set",NULL);
98 return (EOF);}
99
100 /*posn must be between 0 and 9 */
101 if (posn < 0) {
102 posn = 0;
103 } else if (posn > mfile->labels.number) {
104 posn = mfile->labels.number;
105 }
106
107 if (mfile->labels.labels[posn] != NULL)
108 free(mfile->labels.labels[posn]);
109
110 /* if label == NULL reset the value and compress set */
111 if (label == NULL) {
112 mfile->labels.labels[posn] = NULL;
113 for ( i=posn ; i!=10 ; i++)
114 if (mfile->labels.labels[i] == NULL)
115 for ( j=i+1 ; j!=10; j++)
116 if (mfile->labels.labels[j] != NULL) {
117 mfile->labels.labels[i] = mfile->labels.labels[j];
118 mfile->labels.labels[j] = NULL;
119 break;
120 }
121 }
122 else
123 mfile->labels.labels[posn] = strdup(label);
124
125 /* recalculate number */
126 for ( i=0 ; i!=10 ; i++)
127 if (mfile->labels.labels[i] == NULL)
128 break;
129 mfile->labels.number = i;
130
131 return posn;
132 }
133
134 /*! Get the label corresponding to position posn
135 \param mfile (const CMMFile *)
136 \param posn (int) desired label number
137 \return pointer to label posn */
ccp4_cmap_get_label(const CMMFile * mfile,int posn)138 char *ccp4_cmap_get_label(const CMMFile *mfile, int posn)
139 {
140 char *label;
141 if (mfile == NULL) {
142 ccp4_signal( CCP4_ERRLEVEL(3) | CMAP_ERRNO(CMERR_NoChannel),
143 "ccp4_cmap_get_label",NULL);
144 return (NULL);}
145
146 if (posn < 0 || posn >= mfile->labels.number)
147 label = NULL;
148 else
149 label = mfile->labels.labels[posn];
150
151 return label;
152 }
153
154 /*! Return the number of labels.
155 \param mfile (CMMFile *)
156 \return the number of labels */
ccp4_cmap_number_label(const CMMFile * mfile)157 int ccp4_cmap_number_label(const CMMFile *mfile)
158 {
159 return mfile->labels.number;
160 }
161
162 /*! Get the label corresponding to the title
163 wrapping ccp4_cmap_get_label.
164 \param mfile (const CMMFile *)
165 \return pointer to label 0, or NULL */
ccp4_cmap_get_title(const CMMFile * mfile)166 char *ccp4_cmap_get_title(const CMMFile *mfile)
167 {
168 return ccp4_cmap_get_label(mfile, 0);
169 }
170
171 /*! Set the label corresponding to the title,
172 wrapping ccp4_cmap_set_label
173 \param mfile (CMMFile *)
174 \param label
175 \return 0 or EOF on failure */
ccp4_cmap_set_title(CMMFile * mfile,const char * title)176 int ccp4_cmap_set_title(CMMFile *mfile, const char *title)
177 {
178 return ccp4_cmap_set_label(mfile, title, 0);
179 }
180