cfad47cfa3/tads3/vmhosttx.cpp

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* 
2
 *   Copyright (c) 2002 by Michael J. Roberts.  All Rights Reserved.
3
 *   
4
 *   Please see the accompanying license file, LICENSE.TXT, for information
5
 *   on using and copying this software.  
6
 */
7
/*
8
Name
9
  vmhosttx.cpp - text-only host interface implementation
10
Function
11
  Provides a base class for the T3 VM Host Interface for implementing
12
  text-only applications.
13
Notes
14
  
15
Modified
16
  06/16/02 MJRoberts  - Creation
17
*/
18
19
#include "os.h"
20
#include "t3std.h"
21
#include "vmhash.h"
22
#include "vmhost.h"
23
#include "vmhosttx.h"
24
25
/* ------------------------------------------------------------------------ */
26
/*
27
 *   Hash table entry for a resource descriptor 
28
 */
29
class CResEntry: public CVmHashEntryCI
30
{
31
public:
32
    CResEntry(const char *resname, size_t resnamelen, int copy,
33
              unsigned long ofs, unsigned long siz, int fileno)
34
        : CVmHashEntryCI(resname, resnamelen, copy)
35
    {
36
        /* remember the file locator information */
37
        fileno_ = fileno;
38
        ofs_ = ofs;
39
        siz_ = siz;
40
        link_ = 0;
41
    }
42
43
    CResEntry(const char *resname, size_t resnamelen, int copy,
44
              const char *fname, size_t fnamelen)
45
        : CVmHashEntryCI(resname, resnamelen, copy)
46
    {
47
        /* save the local filename */
48
        link_ = lib_copy_str(fname, fnamelen);
49
50
        /* it's not in a resource file */
51
        fileno_ = 0;
52
        ofs_ = 0;
53
        siz_ = 0;
54
    }
55
56
    ~CResEntry()
57
    {
58
        lib_free_str(link_);
59
    }
60
61
    /* file number (this is an index in the hostifc's ext_ array) */
62
    int fileno_;
63
64
    /* byte offset of the start of the resource data in the file */
65
    unsigned long ofs_;
66
67
    /* byte size of the resource data */
68
    unsigned long siz_;
69
70
    /* local filename, for a resource link (rather than a stored resource) */
71
    char *link_;
72
};
73
74
/* ------------------------------------------------------------------------ */
75
/*
76
 *   construction 
77
 */
78
CVmHostIfcText::CVmHostIfcText()
79
{
80
    /* create our hash table */
81
    restab_ = new CVmHashTable(128, new CVmHashFuncCI(), TRUE);
82
83
    /* allocate an initial set of external resource filename entries */
84
    ext_max_ = 10;
85
    ext_ = (char **)t3malloc(ext_max_ * sizeof(ext_[0]));
86
87
    /* we use slot zero for the image filename, which we don't know yet */
88
    ext_cnt_ = 1;
89
    ext_[0] = 0;
90
91
    /* no resource directory specified yet */
92
    res_dir_ = 0;
93
}
94
95
/*
96
 *   deletion 
97
 */
98
CVmHostIfcText::~CVmHostIfcText()
99
{
100
    size_t i;
101
102
    /* delete our hash table */
103
    delete restab_;
104
105
    /* delete our external filenames */
106
    for (i = 0 ; i < ext_cnt_ ; ++i)
107
        lib_free_str(ext_[i]);
108
109
    /* delete our array of external filename entries */
110
    t3free(ext_);
111
112
    /* delete our resource directory path */
113
    lib_free_str(res_dir_);
114
}
115
116
/* 
117
 *   set the image file name - we always use resource file slot zero to
118
 *   store the image file 
119
 */
120
void CVmHostIfcText::set_image_name(const char *fname)
121
{
122
    /* free any old name string */
123
    lib_free_str(ext_[0]);
124
125
    /* remember the new name */
126
    ext_[0] = lib_copy_str(fname);
127
}
128
129
/*
130
 *   set the resource directory 
131
 */
132
void CVmHostIfcText::set_res_dir(const char *dir)
133
{
134
    /* forget any previous setting, and remember the new path */
135
    lib_free_str(res_dir_);
136
    res_dir_ = lib_copy_str(dir);
137
}
138
139
/* 
140
 *   add a resource file 
141
 */
142
int CVmHostIfcText::add_resfile(const char *fname)
143
{
144
    /* expand the resource file list if necessary */
145
    if (ext_cnt_ == ext_max_)
146
    {
147
        /* bump up the maximum a bit */
148
        ext_max_ += 10;
149
150
        /* reallocate the entry pointer array */
151
        ext_ = (char **)t3realloc(ext_, ext_max_ * sizeof(ext_[0]));
152
    }
153
154
    /* store the new entry */
155
    ext_[ext_cnt_++] = lib_copy_str(fname);
156
157
    /* 
158
     *   return the new entry's file number (we've already bumped the index,
159
     *   so it's the current count minus one) 
160
     */
161
    return ext_cnt_ - 1;
162
}
163
164
/* 
165
 *   add a resource 
166
 */
167
void CVmHostIfcText::add_resource(unsigned long ofs, unsigned long siz,
168
                                  const char *resname, size_t resnamelen,
169
                                  int fileno)
170
{
171
    CResEntry *entry;
172
    
173
    /* create a new entry desribing the resource */
174
    entry = new CResEntry(resname, resnamelen, TRUE, ofs, siz, fileno);
175
176
    /* add it to the table */
177
    restab_->add(entry);
178
}
179
180
/* 
181
 *   add a resource 
182
 */
183
void CVmHostIfcText::add_resource(const char *fname, size_t fnamelen,
184
                                  const char *resname, size_t resnamelen)
185
{
186
    CResEntry *entry;
187
188
    /* create a new entry desribing the resource */
189
    entry = new CResEntry(resname, resnamelen, TRUE, fname, fnamelen);
190
191
    /* add it to the table */
192
    restab_->add(entry);
193
}
194
195
/* 
196
 *   find a resource 
197
 */
198
osfildef *CVmHostIfcText::find_resource(const char *resname,
199
                                        size_t resnamelen,
200
                                        unsigned long *res_size)
201
{
202
    CResEntry *entry;
203
    osfildef *fp;
204
    char buf[OSFNMAX];
205
    char *fname;
206
    char fname_buf[OSFNMAX];
207
    char path[OSFNMAX];
208
209
    /* try finding an entry in the resource map */
210
    entry = (CResEntry *)restab_->find(resname, resnamelen);
211
    if (entry != 0)
212
    {
213
        /* found it - check the type */
214
        if (entry->link_ == 0)
215
        {
216
            /* it's a stored binary resource - load it */
217
            fp = osfoprb(ext_[entry->fileno_], OSFTBIN);
218
            
219
            /* if that succeeded, seek to the start of the resource */
220
            if (fp != 0)
221
                osfseek(fp, entry->ofs_, OSFSK_SET);
222
            
223
            /* tell the caller the size of the resource */
224
            *res_size = entry->siz_;
225
            
226
            /* return the file handle */
227
            return fp;
228
        }
229
        else
230
        {
231
            /* it's a link to a a local file */
232
            fname = entry->link_;
233
        }
234
    }
235
    else
236
    {
237
        /* 
238
         *   There's no entry in the resource map, so convert the resource
239
         *   name from the URL notation to local file system conventions,
240
         *   and look for a file with the given name.
241
         *   
242
         *   First, make a null-terminated copy of the resource name,
243
         *   limiting the copy to our buffer size.  
244
         */
245
        if (resnamelen > sizeof(buf) - 1)
246
            resnamelen = sizeof(buf) - 1;
247
        memcpy(buf, resname, resnamelen);
248
        buf[resnamelen] = '\0';
249
250
        /* convert the resource name to a URL */
251
        os_cvt_url_dir(fname_buf, sizeof(fname_buf), buf, FALSE);
252
        fname = fname_buf;
253
    }
254
255
    /* 
256
     *   If we get this far, it's because we have a local file name in
257
     *   'fname' that we need to loo up.  
258
     */
259
260
    /* 
261
     *   external resources are relative to the image file, so make sure we
262
     *   have an image file name 
263
     */
264
    if (ext_[0] == 0)
265
        return 0;
266
267
    /* get the path to the image file */
268
    os_get_path_name(path, sizeof(path), ext_[0]);
269
270
    /* 
271
     *   build the full path name by combining the image file path with the
272
     *   relative path we got from the resource name URL, as converted local
273
     *   file system conventions 
274
     */
275
    os_build_full_path(buf, sizeof(buf), path, fname);
276
277
    /* try opening the file */
278
    fp = osfoprb(buf, OSFTBIN);
279
280
    /* return failure if we couldn't find the file */
281
    if (fp == 0)
282
        return 0;
283
284
    /* 
285
     *   the entire file is the resource data, so figure out how big the file
286
     *   is, and tell the caller that the resource size is the file size 
287
     */
288
    osfseek(fp, 0, OSFSK_END);
289
    *res_size = osfpos(fp);
290
291
    /* 
292
     *   seek back to the start of the resource data (which is simply the
293
     *   start of the file, since the entire file is the resource data) 
294
     */
295
    osfseek(fp, 0, OSFSK_SET);
296
        
297
    /* return the file handle */
298
    return fp;
299
}
300
301
/* 
302
 *   determine if a resource exists 
303
 */
304
int CVmHostIfcText::resfile_exists(const char *resname, size_t resnamelen)
305
{
306
    osfildef *fp;
307
    unsigned long res_size;
308
309
    /* try opening the resource file */
310
    fp = find_resource(resname, resnamelen, &res_size);
311
312
    /* check to see if we successfully opened the resource */
313
    if (fp != 0)
314
    {
315
        /* found it - close the file and return success */
316
        osfcls(fp);
317
        return TRUE;
318
    }
319
    else
320
    {
321
        /* couldn't find it - indicate failure */
322
        return FALSE;
323
    }
324
}
325