1 /*
2 * Copyright 2012 Peter Curtis
3 *
4 * This file is part of libocad.
5 *
6 * libocad is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * libocad is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with libocad. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21
22 #include "libocad.h"
23
24 #define F_TEMPL "\ts%d\tx%d\ty%d\ta%lg\tu%lg\tv%lg\td%d\tp%d\tt%d\to%d"
25
ocad_to_background(OCADBackground * bg,OCADCString * templ)26 int ocad_to_background(OCADBackground* bg, OCADCString* templ) {
27 char tmp[1024];
28 int sz;
29 char *p = strchr(templ->str, 9);
30 if (p == NULL) return -1;
31 sz = p - templ->str;
32 memcpy(tmp, templ->str, sz); tmp[sz] = 0;
33 bg->filename = (char *)my_strdup(tmp);
34 if (10 == sscanf(p, F_TEMPL,
35 &(bg->s), &(bg->trnx), &(bg->trny), &(bg->angle), &(bg->sclx), &(bg->scly),
36 &(bg->dimming), &(bg->p), (int *)&(bg->transparent), &(bg->o))) {
37 return 0;
38 }
39 return -1;
40 }
41
ocad_string_size_background(OCADBackground * bg)42 int ocad_string_size_background(OCADBackground *bg) {
43 char tmp[1024];
44 snprintf(tmp, 1024, "%s" F_TEMPL,
45 bg->filename, bg->s, bg->trnx, bg->trny, bg->angle, bg->sclx, bg->scly,
46 bg->dimming, bg->p, bg->transparent, bg->o);
47 return strlen(tmp);
48 }
49
ocad_background_to_string(char * buf,int size,OCADBackground * bg)50 void ocad_background_to_string(char *buf, int size, OCADBackground *bg) {
51 snprintf(buf, size, "%s" F_TEMPL,
52 bg->filename, bg->s, bg->trnx, bg->trny, bg->angle, bg->sclx, bg->scly,
53 bg->dimming, bg->p, bg->transparent, bg->o);
54 }
55
56
57
58
ocad_string_index_first(OCADFile * pfile)59 OCADStringIndex *ocad_string_index_first(OCADFile *pfile) {
60 dword offs;
61 if (!pfile->header) return NULL;
62 offs = pfile->header->ostringidx;
63 if (offs == 0) return NULL;
64 return (OCADStringIndex *)(pfile->buffer + offs);
65 }
66
ocad_string_index_next(OCADFile * pfile,OCADStringIndex * current)67 OCADStringIndex *ocad_string_index_next(OCADFile *pfile, OCADStringIndex *current) {
68 dword offs;
69 if (!pfile->header || !current) return NULL;
70 offs = current->next;
71 if (offs == 0) return NULL;
72 return (OCADStringIndex *)(pfile->buffer + offs);
73 }
74
ocad_string_entry_at(OCADFile * pfile,OCADStringIndex * current,int index)75 OCADStringEntry *ocad_string_entry_at(OCADFile *pfile, OCADStringIndex *current, int index) {
76 if (!pfile->header || !current) return NULL;
77 if (index < 0 || index >= 256) return NULL;
78 return &(current->entry[index]);
79 }
80
ocad_string_entry_new(OCADFile * pfile,u32 size)81 OCADStringEntry *ocad_string_entry_new(OCADFile *pfile, u32 size) {
82 OCADStringEntry *empty = NULL;
83 OCADStringIndex *idx;
84 u32 last_idx_offset = 0;
85 u32 empty_offset = 0; // offset to first empty (size=0) index entry, if needed
86
87 if (!pfile->header) return NULL;
88 for (idx = ocad_string_index_first(pfile); idx != NULL; idx = ocad_string_index_next(pfile, idx)) {
89 int i;
90 last_idx_offset = (u8*)idx - pfile->buffer;
91 for (i = 0; i < 256; i++) {
92 OCADStringEntry *entry = &(idx->entry[i]);
93 if (entry->type == 0) {
94 if (entry->size == 0 && empty_offset == 0) empty_offset = (u8*)&idx->entry[i] - pfile->buffer;
95 else if (entry->size >= size) return entry;
96 }
97 }
98 }
99
100 if (empty_offset == 0) {
101 // We don't have any empty entries - need to create a new one!
102 if (last_idx_offset == 0) return NULL; // we don't support adding strings to files without string index block
103 ocad_file_reserve(pfile, sizeof(OCADStringIndex));
104 idx = (OCADStringIndex*)(pfile->buffer + last_idx_offset);
105 idx->next = pfile->size;
106 idx = (OCADStringIndex*)(pfile->buffer + pfile->size);
107 pfile->size += sizeof(OCADStringIndex);
108 empty_offset = (u8*)&idx->entry[0] - pfile->buffer;
109 }
110
111 // There exists an empty index entry. We can allocate a new object and fill it
112 ocad_file_reserve(pfile, size);
113 empty = (OCADStringEntry*)(pfile->buffer + empty_offset);
114 empty->size = size;
115 empty->ptr = pfile->size;
116 pfile->size += empty->size;
117
118 return empty;
119 }
120
ocad_string_remove(OCADFile * pfile,OCADStringEntry * entry)121 int ocad_string_remove(OCADFile *pfile, OCADStringEntry *entry) {
122 entry->type = 0;
123 return 0;
124 }
125
ocad_string_entry_iterate(OCADFile * pfile,OCADStringEntryCallback callback,void * param)126 bool ocad_string_entry_iterate(OCADFile *pfile, OCADStringEntryCallback callback, void *param) {
127 OCADStringIndex *idx;
128 for (idx = ocad_string_index_first(pfile); idx != NULL; idx = ocad_string_index_next(pfile, idx)) {
129 int i;
130 for (i = 0; i < 256; i++) {
131 OCADStringEntry *entry = &(idx->entry[i]);
132 if (entry->type != 0) {
133 if (!callback(param, pfile, entry)) return FALSE;
134 }
135 }
136 }
137 return TRUE;
138 }
139
ocad_string_at(OCADFile * pfile,OCADStringIndex * current,int index)140 OCADCString *ocad_string_at(OCADFile *pfile, OCADStringIndex *current, int index) {
141 dword offs;
142 OCADStringEntry *entry = ocad_string_entry_at(pfile, current, index);
143 if (entry == NULL) return NULL;
144 offs = entry->ptr;
145 if (offs == 0) return NULL;
146 return (OCADCString *)(pfile->buffer + offs);
147 }
148
ocad_string(OCADFile * pfile,OCADStringEntry * entry)149 OCADCString *ocad_string(OCADFile *pfile, OCADStringEntry *entry) {
150 if (!pfile->header) return NULL;
151 if (entry == NULL || entry->ptr == 0) return NULL;
152 return (OCADCString *)(pfile->buffer + entry->ptr);
153 }
154
ocad_string_add_background(OCADFile * pfile,OCADBackground * bg)155 int ocad_string_add_background(OCADFile *pfile, OCADBackground *bg) {
156 OCADStringEntry *entry;
157 OCADCString *templ;
158 int size = ocad_string_size_background(bg);
159 entry = ocad_string_entry_new(pfile, size);
160 if (entry == NULL) return -1;
161 templ = ocad_string(pfile, entry);
162 ocad_background_to_string(templ->str, size, bg);
163 entry->type = 8;
164 entry->res1 = 0;
165 entry->res2 = 0;
166 return 0;
167 }
168