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