00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029 #include "shapefile.h"
00030 #include "u7drag.h"
00031 #include "shapegroup.h"
00032 #include "shapevga.h"
00033 #include "shapelst.h"
00034 #include "chunklst.h"
00035 #include "paledit.h"
00036 #include "utils.h"
00037 #include "Flex.h"
00038 #include "exceptions.h"
00039 #include "combo.h"
00040 #include "studio.h"
00041
00042 using std::vector;
00043 using std::string;
00044 using std::cerr;
00045 using std::endl;
00046 using std::ofstream;
00047
00048
00049
00050
00051
00052 Shape_file_info::~Shape_file_info
00053 (
00054 )
00055 {
00056 delete groups;
00057 delete browser;
00058 }
00059
00060
00061
00062
00063
00064
00065
00066 Object_browser *Shape_file_info::get_browser
00067 (
00068 Shape_file_info *vgafile,
00069 unsigned char *palbuf
00070 )
00071 {
00072 if (browser)
00073 return browser;
00074 browser = create_browser(vgafile, palbuf, 0);
00075
00076 gtk_widget_ref(browser->get_widget());
00077 return browser;
00078 }
00079
00080
00081
00082
00083
00084 Image_file_info::~Image_file_info
00085 (
00086 )
00087 {
00088 delete ifile;
00089 }
00090
00091
00092
00093
00094
00095 Object_browser *Image_file_info::create_browser
00096 (
00097 Shape_file_info *vgafile,
00098 unsigned char *palbuf,
00099 Shape_group *g
00100 )
00101 {
00102 Shape_chooser *chooser = new Shape_chooser(ifile, palbuf, 400, 64,
00103 g, this);
00104
00105 if (strcasecmp(basename.c_str(), "fonts.vga") == 0)
00106 chooser->set_framenum0('A');
00107 if (this == vgafile)
00108 {
00109 chooser->set_shapes_file(
00110 (Shapes_vga_file *) vgafile->get_ifile());
00111 }
00112 return chooser;
00113 }
00114
00115
00116
00117
00118
00119 void Image_file_info::flush
00120 (
00121 )
00122 {
00123 if (!modified)
00124 return;
00125 modified = false;
00126 int nshapes = ifile->get_num_shapes();
00127 int shnum;
00128 Shape **shapes = new Shape *[nshapes];
00129 for (shnum = 0; shnum < nshapes; shnum++)
00130 shapes[shnum] = ifile->extract_shape(shnum);
00131 string filestr("<PATCH>/");
00132 filestr += basename;
00133
00134 write_file(filestr.c_str(), shapes, nshapes, !ifile->is_flex());
00135 delete [] shapes;
00136
00137 unsigned char buf[Exult_server::maxlength];
00138 unsigned char *ptr = &buf[0];
00139 Write2(ptr, ifile->get_u7drag_type());
00140 ExultStudio *studio = ExultStudio::get_instance();
00141 studio->send_to_server(Exult_server::reload_shapes, buf, ptr - buf);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 bool Image_file_info::revert
00151 (
00152 )
00153 {
00154 if (modified)
00155 {
00156 ifile->load(pathname.c_str());
00157 modified = false;
00158 }
00159 return true;
00160 }
00161
00162
00163
00164
00165
00166
00167 void Image_file_info::write_file
00168 (
00169 const char *pathname,
00170 Shape **shapes,
00171 int nshapes,
00172 bool single
00173 )
00174 {
00175 ofstream out;
00176 U7open(out, pathname);
00177 if (single)
00178 {
00179 if (nshapes)
00180 shapes[0]->write(out);
00181 out.flush();
00182 if (!out.good())
00183 throw file_write_exception(pathname);
00184 out.close();
00185 return;
00186 }
00187 Flex_writer writer(out, "Written by ExultStudio", nshapes);
00188
00189 for (int shnum = 0; shnum < nshapes; shnum++)
00190 {
00191 shapes[shnum]->write(out);
00192 writer.mark_section_done();
00193 }
00194 if (!writer.close())
00195 throw file_write_exception(pathname);
00196 }
00197
00198
00199
00200
00201
00202 Chunks_file_info::~Chunks_file_info
00203 (
00204 )
00205 {
00206 delete file;
00207 }
00208
00209
00210
00211
00212
00213 Object_browser *Chunks_file_info::create_browser
00214 (
00215 Shape_file_info *vgafile,
00216 unsigned char *palbuf,
00217 Shape_group *g
00218 )
00219 {
00220
00221 return new Chunk_chooser(vgafile->get_ifile(), *file, palbuf,
00222 400, 64, g);
00223 }
00224
00225
00226
00227
00228
00229 void Chunks_file_info::flush
00230 (
00231 )
00232 {
00233 if (!modified)
00234 return;
00235 modified = false;
00236 cerr << "Chunks should be stored by Exult" << endl;
00237 }
00238
00239
00240
00241
00242
00243 Flex_file_info::Flex_file_info
00244 (
00245 const char *bnm,
00246 const char *pnm,
00247 Flex *fl,
00248 Shape_group_file *g
00249 ) : Shape_file_info(bnm, pnm, g), flex(fl), write_flat(false)
00250 {
00251 entries.resize(flex->number_of_objects());
00252 lengths.resize(entries.size());
00253 }
00254
00255
00256
00257
00258
00259 Flex_file_info::Flex_file_info
00260 (
00261 const char *bnm,
00262 const char *pnm,
00263 int size
00264 ) : Shape_file_info(bnm, pnm, 0), flex(0), write_flat(true)
00265 {
00266 entries.resize(size > 0);
00267 lengths.resize(entries.size());
00268 if (size > 0)
00269 {
00270 std::ifstream in;
00271 U7open(in, pnm);
00272 entries[0] = new char[size];
00273 in.read(entries[0], size);
00274 lengths[0] = size;
00275 }
00276 }
00277
00278
00279
00280
00281
00282 Flex_file_info::~Flex_file_info
00283 (
00284 )
00285 {
00286 delete flex;
00287 int cnt = entries.size();
00288 for (int i = 0; i < cnt; i++)
00289 delete entries[i];
00290 }
00291
00292
00293
00294
00295
00296 char *Flex_file_info::get
00297 (
00298 int i,
00299 size_t& len
00300 )
00301 {
00302 if (i >= 0 && i < entries.size())
00303 {
00304 if (!entries[i])
00305 {
00306 entries[i] = flex->retrieve(i, len);
00307 lengths[i] = len;
00308 }
00309 len = lengths[i];
00310 return entries[i];
00311 }
00312 else
00313 return 0;
00314 }
00315
00316
00317
00318
00319
00320 void Flex_file_info::set
00321 (
00322 int i,
00323 char *newentry,
00324 int entlen
00325 )
00326 {
00327 if (i < 0 || i > entries.size())
00328 return;
00329 if (i == entries.size())
00330 {
00331 entries.push_back(newentry);
00332 lengths.push_back(entlen);
00333 }
00334 else
00335 {
00336 delete entries[i];
00337 entries[i] = newentry;
00338 lengths[i] = entlen;
00339 }
00340 }
00341
00342
00343
00344
00345
00346 void Flex_file_info::swap
00347 (
00348 int i
00349 )
00350 {
00351 assert (i >= 0 && i < entries.size() - 1);
00352 char *tmpent = entries[i];
00353 int tmplen = lengths[i];
00354 entries[i] = entries[i + 1];
00355 lengths[i] = lengths[i + 1];
00356 entries[i + 1] = tmpent;
00357 lengths[i + 1] = tmplen;
00358 }
00359
00360
00361
00362
00363
00364 void Flex_file_info::remove
00365 (
00366 int i
00367 )
00368 {
00369 assert (i >= 0 && i < entries.size());
00370 delete entries[i];
00371 entries.erase(entries.begin() + i);
00372 lengths.erase(lengths.begin() + i);
00373 }
00374
00375
00376
00377
00378
00379 Object_browser *Flex_file_info::create_browser
00380 (
00381 Shape_file_info *vgafile,
00382 unsigned char *palbuf,
00383 Shape_group *g
00384 )
00385 {
00386 const char *bname = basename.c_str();
00387 if (strcasecmp(bname, "palettes.flx") == 0 ||
00388 strcasecmp(".pal", bname + strlen(bname) - 4) == 0)
00389 return new Palette_edit(this);
00390 return new Combo_chooser(vgafile->get_ifile(), this, palbuf,
00391 400, 64, g);
00392 }
00393
00394
00395
00396
00397
00398 void Flex_file_info::flush
00399 (
00400 )
00401 {
00402 if (!modified)
00403 return;
00404 modified = false;
00405 int cnt = entries.size();
00406 size_t len;
00407 int i;
00408 for (i = 0; i < cnt; i++)
00409 {
00410 if (!entries[i])
00411 get(i, len);
00412 }
00413 ofstream out;
00414 string filestr("<PATCH>/");
00415 filestr += basename;
00416 U7open(out, filestr.c_str());
00417 if (cnt <= 1 && write_flat)
00418 {
00419 if (cnt)
00420 out.write(entries[0], lengths[0]);
00421 out.close();
00422 if (!out.good())
00423 throw file_write_exception(filestr.c_str());
00424 return;
00425 }
00426 Flex_writer writer(out, "Written by ExultStudio", cnt);
00427
00428 for (int i = 0; i < cnt; i++)
00429 {
00430 out.write(entries[i], lengths[i]);
00431 writer.mark_section_done();
00432 }
00433 if (!writer.close())
00434 throw file_write_exception(filestr.c_str());
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 bool Flex_file_info::revert
00444 (
00445 )
00446 {
00447 if (!modified)
00448 return true;
00449 modified = false;
00450 int cnt = entries.size();
00451 for (int i = 0; i < cnt; i++)
00452 {
00453 delete entries[i];
00454 entries[i] = 0;
00455 lengths[i] = 0;
00456 }
00457 if (flex)
00458 {
00459 cnt = flex->number_of_objects();
00460 entries.resize(cnt);
00461 lengths.resize(entries.size());
00462 }
00463 else
00464 {
00465 std::ifstream in;
00466 U7open(in, pathname.c_str());
00467 in.seekg(0, std::ios::end);
00468 int sz = in.tellg();
00469 cnt = sz > 0 ? 1 : 0;
00470 entries.resize(cnt);
00471 lengths.resize(entries.size());
00472 in.seekg(0);
00473 if (cnt)
00474 {
00475 entries[0] = new char[sz];
00476 in.read(entries[0], sz);
00477 lengths[0] = sz;
00478 }
00479 }
00480 return true;
00481 }
00482
00483
00484
00485
00486
00487 Shape_file_set::~Shape_file_set
00488 (
00489 )
00490 {
00491 for (vector<Shape_file_info *>::iterator it = files.begin();
00492 it != files.end(); ++it)
00493 delete (*it);
00494 }
00495
00496
00497
00498
00499
00500
00501
00502 static bool Create_file
00503 (
00504 const char *basename,
00505 const string& pathname
00506 )
00507 {
00508 int namelen = strlen(basename);
00509 if (strcasecmp(".flx", basename + namelen - 4) == 0)
00510 {
00511 ofstream out;
00512 U7open(out, pathname.c_str());
00513 Flex_writer writer(out, "Written by ExultStudio", 0);
00514 if (!writer.close())
00515 throw file_write_exception(pathname.c_str());
00516 return true;
00517 }
00518 else if (strcasecmp(".pal", basename + namelen - 4) == 0)
00519 {
00520 ofstream out;
00521 U7open(out, pathname.c_str());
00522 out.close();
00523 return true;
00524 }
00525 return false;
00526 }
00527
00528
00529
00530
00531
00532
00533
00534 Shape_file_info *Shape_file_set::create
00535 (
00536 const char *basename
00537 )
00538 {
00539
00540 for (vector<Shape_file_info *>::iterator it = files.begin();
00541 it != files.end(); ++it)
00542 if (strcasecmp((*it)->basename.c_str(), basename) == 0)
00543 return *it;
00544
00545 string sstr = string("<STATIC>/") + basename;
00546 string pstr = string("<PATCH>/") + basename;
00547 const char *spath = sstr.c_str(), *ppath = pstr.c_str();
00548 bool sexists = U7exists(spath);
00549 bool pexists = U7exists(ppath);
00550 if (!sexists && !pexists)
00551 if (!(pexists = Create_file(basename, ppath)))
00552 return 0;
00553
00554 const char *fullname = pexists ? ppath : spath;
00555 string group_name(basename);
00556 group_name += ".grp";
00557 Shape_group_file *groups = new Shape_group_file(group_name.c_str());
00558 if (strcasecmp(basename, "shapes.vga") == 0)
00559 return append(new Image_file_info(basename, fullname,
00560 new Shapes_vga_file(spath, U7_SHAPE_SHAPES, ppath),
00561 groups));
00562 else if (strcasecmp(basename, "gumps.vga") == 0)
00563 return append(new Image_file_info(basename, fullname,
00564 new Vga_file(spath, U7_SHAPE_GUMPS, ppath), groups));
00565 else if (strcasecmp(basename, "faces.vga") == 0)
00566 return append(new Image_file_info(basename, fullname,
00567 new Vga_file(spath, U7_SHAPE_FACES, ppath), groups));
00568 else if (strcasecmp(basename, "sprites.vga") == 0)
00569 return append(new Image_file_info(basename, fullname,
00570 new Vga_file(spath, U7_SHAPE_SPRITES, ppath), groups));
00571 else if (strcasecmp(basename, "paperdol.vga") == 0)
00572 return append(new Image_file_info(basename, fullname,
00573 new Vga_file(spath, U7_SHAPE_PAPERDOL, ppath), groups));
00574 else if (strcasecmp(basename, "fonts.vga") == 0)
00575 return append(new Image_file_info(basename, fullname,
00576 new Vga_file(spath, U7_SHAPE_FONTS, ppath), groups));
00577 else if (strcasecmp(basename, "u7chunks") == 0)
00578 {
00579 std::ifstream *file = new std::ifstream;
00580 U7open(*file, fullname);
00581 return append(new Chunks_file_info(basename, fullname,
00582 file, groups));
00583 }
00584 else if (strcasecmp(basename, "combos.flx") == 0 ||
00585 strcasecmp(basename, "palettes.flx") == 0)
00586 return append(new Flex_file_info(basename, fullname,
00587 new Flex(fullname), groups));
00588 else if (strcasecmp(".pal", basename + strlen(basename) - 4) == 0)
00589 {
00590 std::ifstream in;
00591 U7open(in, fullname);
00592 in.seekg(0, std::ios::end);
00593 int sz = in.tellg();
00594 return append(new Flex_file_info(basename, fullname, sz));
00595 }
00596 else
00597 {
00598 Vga_file *ifile = new Vga_file(spath, U7_SHAPE_UNK, ppath);
00599 if (ifile->is_good())
00600 return append(new Image_file_info(basename, fullname,
00601 ifile, groups));
00602 delete ifile;
00603 }
00604 cerr << "Error opening image file '" << basename << "'.\n";
00605 return 0;
00606 }
00607
00608
00609
00610
00611
00612 void Shape_file_set::flush
00613 (
00614 )
00615 {
00616 for (vector<Shape_file_info *>::iterator it = files.begin();
00617 it != files.end(); ++it)
00618 (*it)->flush();
00619 }
00620
00621
00622
00623
00624
00625 bool Shape_file_set::is_modified
00626 (
00627 )
00628 {
00629 for (vector<Shape_file_info *>::iterator it = files.begin();
00630 it != files.end(); ++it)
00631 if ((*it)->modified)
00632 return true;
00633 return false;
00634 }