111 } |
111 } |
112 |
112 |
113 // ============================================================================= |
113 // ============================================================================= |
114 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
114 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
115 // ============================================================================= |
115 // ============================================================================= |
116 FILE* openLDrawFile (str path, bool bSubDirectories) { |
116 FILE* openLDrawFile (str relpath, bool subdirs) { |
117 str zTruePath = path; |
|
118 |
|
119 #ifndef WIN32 |
117 #ifndef WIN32 |
120 zTruePath.replace ("\\", "/"); |
118 relpath.replace ("\\", "/"); |
121 #endif // WIN32 |
119 #endif // WIN32 |
122 |
120 |
123 FILE* fp = fopen (path.chars (), "r"); |
121 printf ("Trying %s\n", relpath.chars ()); |
124 str zFilePath; |
122 FILE* fp = fopen (relpath.chars (), "r"); |
|
123 str fullPath; |
125 |
124 |
126 if (fp != null) |
125 if (fp != null) |
127 return fp; |
126 return fp; |
128 |
127 |
129 if (~io_ldpath.value) { |
128 if (~io_ldpath.value) { |
130 // Try with just the LDraw path first |
129 // Try with just the LDraw path first |
131 zFilePath = fmt ("%s" DIRSLASH "%s", |
130 fullPath = fmt ("%s" DIRSLASH "%s", io_ldpath.value.chars(), relpath.chars()); |
132 io_ldpath.value.chars(), zTruePath.chars()); |
131 printf ("Trying %s\n", fullPath.chars()); |
133 logf ("Trying %s\n", zFilePath.chars()); |
132 |
134 |
133 fp = fopen (fullPath, "r"); |
135 fp = fopen (zFilePath, "r"); |
|
136 if (fp != null) |
134 if (fp != null) |
137 return fp; |
135 return fp; |
138 |
136 |
139 if (bSubDirectories) { |
137 if (subdirs) { |
140 char const* saSubdirectories[] = { |
138 char const* saSubdirectories[] = { |
141 "parts", |
139 "parts", |
142 "p", |
140 "p", |
143 }; |
141 }; |
144 |
142 |
145 for (char const* sSubdir : saSubdirectories) { |
143 for (char const* sSubdir : saSubdirectories) { |
146 zFilePath = fmt ("%s" DIRSLASH "%s" DIRSLASH "%s", |
144 fullPath = fmt ("%s" DIRSLASH "%s" DIRSLASH "%s", |
147 io_ldpath.value.chars(), sSubdir, zTruePath.chars()); |
145 io_ldpath.value.chars(), sSubdir, relpath.chars()); |
148 printf ("try %s\n", zFilePath.chars()); |
146 printf ("Trying %s\n", fullPath.chars()); |
149 |
147 |
150 fp = fopen (zFilePath.chars (), "r"); |
148 fp = fopen (fullPath.chars (), "r"); |
151 |
149 |
152 if (fp) |
150 if (fp) |
153 return fp; |
151 return fp; |
154 } |
152 } |
155 } |
153 } |
306 } |
304 } |
307 |
305 |
308 // ============================================================================= |
306 // ============================================================================= |
309 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
307 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
310 // ============================================================================= |
308 // ============================================================================= |
311 void addRecentFile (str zPath) { |
309 void addRecentFile (str path) { |
312 long lPos = io_recentfiles.value.first (zPath); |
310 size_t pos = io_recentfiles.value.first (path); |
313 |
311 |
314 // If this file already is in the list, pop it out. |
312 // If this file already is in the list, pop it out. |
315 if (lPos != -1) { |
313 if (pos != npos) { |
316 if (~io_recentfiles.value == ~zPath) |
314 if (~io_recentfiles.value == ~path) |
317 return; // only recent file - do nothing |
315 return; // only recent file - do nothing |
318 |
316 |
319 // Pop it out. |
317 // Pop it out. |
320 str zFront = io_recentfiles.value.substr (0, lPos); |
318 str front = io_recentfiles.value.substr (0, pos); |
321 str zBack = io_recentfiles.value.substr (lPos + ~zPath + 1, -1); |
319 str back; |
322 io_recentfiles.value = zFront + zBack; |
320 |
|
321 if (pos + ~path + 1 < io_recentfiles.value.len ()) |
|
322 back = io_recentfiles.value.substr (pos + ~path + 1, -1); |
|
323 else |
|
324 back = ""; |
|
325 |
|
326 io_recentfiles.value = front + back; |
323 } |
327 } |
324 |
328 |
325 // If there's too many recent files, drop one out. |
329 // If there's too many recent files, drop one out. |
326 while (io_recentfiles.value.count ('@') > 3) |
330 while (io_recentfiles.value.count ('@') > 3) |
327 io_recentfiles.value = io_recentfiles.value.substr (io_recentfiles.value.first ("@") + 1, -1); |
331 io_recentfiles.value = io_recentfiles.value.substr (io_recentfiles.value.first ("@") + 1, -1); |
328 |
332 |
329 // Add the file |
333 // Add the file |
330 if (~io_recentfiles.value > 0) |
334 if (~io_recentfiles.value > 0) |
331 io_recentfiles.value += "@"; |
335 io_recentfiles.value += "@"; |
332 |
336 |
333 io_recentfiles += zPath; |
337 io_recentfiles += path; |
334 |
338 |
335 config::save (); |
339 config::save (); |
336 g_win->updateRecentFilesMenu (); |
340 g_win->updateRecentFilesMenu (); |
337 } |
341 } |
338 |
342 |
400 return true; |
404 return true; |
401 } |
405 } |
402 |
406 |
403 #define CHECK_TOKEN_COUNT(N) \ |
407 #define CHECK_TOKEN_COUNT(N) \ |
404 if (tokens.size() != N) \ |
408 if (tokens.size() != N) \ |
405 return new LDGibberish (zLine, "Bad amount of tokens"); |
409 return new LDGibberish (line, "Bad amount of tokens"); |
406 |
410 |
407 #define CHECK_TOKEN_NUMBERS(MIN,MAX) \ |
411 #define CHECK_TOKEN_NUMBERS(MIN,MAX) \ |
408 for (ushort i = MIN; i <= MAX; ++i) \ |
412 for (ushort i = MIN; i <= MAX; ++i) \ |
409 if (!isNumber (tokens[i])) \ |
413 if (!isNumber (tokens[i])) \ |
410 return new LDGibberish (zLine, fmt ("Token #%u was `%s`, expected a number", \ |
414 return new LDGibberish (line, fmt ("Token #%u was `%s`, expected a number", \ |
411 (i + 1), tokens[i].chars())); |
415 (i + 1), tokens[i].chars())); |
412 |
416 |
413 // ============================================================================= |
417 // ============================================================================= |
414 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
418 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
415 // ============================================================================= |
419 // ============================================================================= |
427 } |
431 } |
428 |
432 |
429 // ============================================================================= |
433 // ============================================================================= |
430 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
434 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
431 // ============================================================================= |
435 // ============================================================================= |
432 LDObject* parseLine (str zLine) { |
436 LDObject* parseLine (str line) { |
433 vector<str> tokens = zLine.split (" ", true); |
437 vector<str> tokens = line.split (" "); |
434 |
438 |
435 if (!tokens.size ()) { |
439 if (!tokens.size ()) { |
436 // Line was empty, or only consisted of whitespace |
440 // Line was empty, or only consisted of whitespace |
437 return new LDEmpty; |
441 return new LDEmpty; |
438 } |
442 } |
439 |
443 |
440 if (~tokens[0] != 1) |
444 if (~tokens[0] != 1) |
441 return new LDGibberish (zLine, "Illogical line code"); |
445 return new LDGibberish (line, "Illogical line code"); |
442 |
446 |
443 const char c = tokens[0][0]; |
447 const char c = tokens[0][0]; |
444 switch (c - '0') { |
448 switch (c - '0') { |
445 case 0: |
449 case 0: |
446 { |
450 { |
488 CHECK_TOKEN_NUMBERS (4, 19) |
492 CHECK_TOKEN_NUMBERS (4, 19) |
489 |
493 |
490 LDRadial::Type eType = LDRadial::NumTypes; |
494 LDRadial::Type eType = LDRadial::NumTypes; |
491 |
495 |
492 for (int i = 0; i < LDRadial::NumTypes; ++i) { |
496 for (int i = 0; i < LDRadial::NumTypes; ++i) { |
493 if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).toupper ().strip (' ') == tokens[3]) { |
497 if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).upper ().strip (' ') == tokens[3]) { |
494 eType = (LDRadial::Type) i; |
498 eType = (LDRadial::Type) i; |
495 break; |
499 break; |
496 } |
500 } |
497 } |
501 } |
498 |
502 |
499 if (eType == LDRadial::NumTypes) |
503 if (eType == LDRadial::NumTypes) |
500 return new LDGibberish (zLine, fmt ("Unknown radial type %s", tokens[3].chars ())); |
504 return new LDGibberish (line, fmt ("Unknown radial type %s", tokens[3].chars ())); |
501 |
505 |
502 LDRadial* obj = new LDRadial; |
506 LDRadial* obj = new LDRadial; |
503 |
507 |
504 obj->radType = eType; // 3 |
508 obj->radType = eType; // 3 |
505 obj->color = atol (tokens[4]); // 4 |
509 obj->color = atol (tokens[4]); // 4 |
530 // Try open the file |
534 // Try open the file |
531 OpenFile* pFile = loadSubfile (tokens[14]); |
535 OpenFile* pFile = loadSubfile (tokens[14]); |
532 |
536 |
533 // If we cannot open the file, mark it an error |
537 // If we cannot open the file, mark it an error |
534 if (!pFile) |
538 if (!pFile) |
535 return new LDGibberish (zLine, "Could not open referred file"); |
539 return new LDGibberish (line, "Could not open referred file"); |
536 |
540 |
537 LDSubfile* obj = new LDSubfile; |
541 LDSubfile* obj = new LDSubfile; |
538 obj->color = atol (tokens[1]); |
542 obj->color = atol (tokens[1]); |
539 obj->pos = parseVertex (tokens, 2); // 2 - 4 |
543 obj->pos = parseVertex (tokens, 2); // 2 - 4 |
540 |
544 |