Add logic to remember imported files' relative filenames, and use

that to try to find them if we can't find them by absolute path.
This is intended to make everything still work if you copy an
entire directory tree of files that import each other.

Also add a mechanism to not paint the scene if we're not sure it's
consistent; otherwise got some crashes on startup. And disable both
text and graphic window when displaying a modal dialog, wasn't
doing that always.

[git-p4: depot-paths = "//depot/solvespace/": change = 1808]
This commit is contained in:
Jonathan Westhues 2008-06-24 21:14:49 -08:00
parent 2ff309590e
commit 12942a74cf
9 changed files with 159 additions and 8 deletions

View File

@ -900,6 +900,12 @@ void GraphicsWindow::Paint(int w, int h) {
glClearDepth(1.0); glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Nasty case when we're reloading the imported files; could be that
// we get an error, so a dialog pops up, and a message loop starts, and
// we have to get called to paint ourselves. If the sketch is screwed
// up, then we could trigger an oops trying to draw.
if(!SS.allConsistent) return;
// Let's use two lights, at the user-specified locations // Let's use two lights, at the user-specified locations
GLfloat f; GLfloat f;
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);

View File

@ -86,6 +86,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.visible", 'b', &(SS.sv.g.visible) }, { 'g', "Group.visible", 'b', &(SS.sv.g.visible) },
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) }, { 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
{ 'g', "Group.impFile", 'P', &(SS.sv.g.impFile) }, { 'g', "Group.impFile", 'P', &(SS.sv.g.impFile) },
{ 'g', "Group.impFileRel", 'P', &(SS.sv.g.impFileRel) },
{ 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) }, { 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) },
{ 'p', "Param.val", 'f', &(SS.sv.p.val) }, { 'p', "Param.val", 'f', &(SS.sv.p.val) },
@ -284,6 +285,8 @@ void SolveSpace::LoadUsingTable(char *key, char *val) {
} }
bool SolveSpace::LoadFromFile(char *filename) { bool SolveSpace::LoadFromFile(char *filename) {
allConsistent = false;
fh = fopen(filename, "rb"); fh = fopen(filename, "rb");
if(!fh) { if(!fh) {
Error("Couldn't read from file '%s'", filename); Error("Couldn't read from file '%s'", filename);
@ -398,6 +401,8 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) {
} }
void SolveSpace::ReloadAllImported(void) { void SolveSpace::ReloadAllImported(void) {
allConsistent = false;
int i; int i;
for(i = 0; i < group.n; i++) { for(i = 0; i < group.n; i++) {
Group *g = &(group.elem[i]); Group *g = &(group.elem[i]);
@ -405,7 +410,37 @@ void SolveSpace::ReloadAllImported(void) {
g->impEntity.Clear(); g->impEntity.Clear();
g->impMesh.Clear(); g->impMesh.Clear();
if(!LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh))) {
FILE *test = fopen(g->impFile, "rb");
if(test) {
fclose(test); // okay, exists
} else {
// It doesn't exist. Perhaps the entire tree has moved, and we
// can use the relative filename to get us back.
if(SS.saveFile[0]) {
char fromRel[MAX_PATH];
strcpy(fromRel, g->impFileRel);
MakePathAbsolute(SS.saveFile, fromRel);
test = fopen(fromRel, "rb");
if(test) {
fclose(test);
// It worked, this is our new absolute path
strcpy(g->impFile, fromRel);
}
}
}
if(LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh))) {
if(SS.saveFile[0]) {
// Record the imported file's name relative to our filename;
// if the entire tree moves, then everything will still work
strcpy(g->impFileRel, g->impFile);
MakePathRelative(SS.saveFile, g->impFileRel);
} else {
// We're not yet saved, so can't make it absolute
strcpy(g->impFileRel, g->impFile);
}
} else {
Error("Failed to load imported file '%s'", g->impFile); Error("Failed to load imported file '%s'", g->impFile);
} }
} }

View File

@ -157,6 +157,7 @@ public:
int remapCache[REMAP_PRIME]; int remapCache[REMAP_PRIME];
char impFile[MAX_PATH]; char impFile[MAX_PATH];
char impFileRel[MAX_PATH];
SMesh impMesh; SMesh impMesh;
EntityList impEntity; EntityList impEntity;

View File

@ -399,6 +399,8 @@ void SolveSpace::GenerateAll(int first, int last) {
deleted.groups, deleted.groups == 1 ? "" : "s"); deleted.groups, deleted.groups == 1 ? "" : "s");
memset(&deleted, 0, sizeof(deleted)); memset(&deleted, 0, sizeof(deleted));
} }
allConsistent = true;
return; return;
pruned: pruned:

View File

@ -58,6 +58,7 @@ int SaveFileYesNoCancel(void);
#define PNG_EXT "png" #define PNG_EXT "png"
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern); BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern); BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
void GetAbsoluteFilename(char *file);
void CheckMenuById(int id, BOOL checked); void CheckMenuById(int id, BOOL checked);
void EnableMenuById(int id, BOOL checked); void EnableMenuById(int id, BOOL checked);
@ -142,6 +143,8 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
double a21, double a22, double a23, double a24, double a21, double a22, double a23, double a24,
double a31, double a32, double a33, double a34, double a31, double a32, double a33, double a34,
double a41, double a42, double a43, double a44); double a41, double a42, double a43, double a44);
void MakePathRelative(char *base, char *path);
void MakePathAbsolute(char *base, char *path);
class System { class System {
public: public:
@ -336,6 +339,11 @@ public:
// The system to be solved. // The system to be solved.
System sys; System sys;
// Everything has been pruned, so we know there's no dangling references
// to entities that don't exist. Before that, we mustn't try to display
// the sketch!
bool allConsistent;
struct { struct {
bool showTW; bool showTW;
bool generateAll; bool generateAll;

View File

@ -383,7 +383,7 @@ void TextWindow::ShowGroupInfo(void) {
} }
if(g->type == Group::IMPORTED) { if(g->type == Group::IMPORTED) {
Printf(true, "%FtIMPORT%E '%s'", g->impFile); Printf(true, "%FtIMPORT%E '%s'", g->impFileRel);
} }
if(g->type == Group::EXTRUDE || if(g->type == Group::EXTRUDE ||

View File

@ -1,5 +1,75 @@
#include "solvespace.h" #include "solvespace.h"
void MakePathRelative(char *basep, char *pathp)
{
int i;
char *p;
char base[MAX_PATH], path[MAX_PATH], out[MAX_PATH];
// Convert everything to lowercase
p = basep;
for(i = 0; *p; p++) {
base[i++] = tolower(*p);
}
base[i++] = '\0';
p = pathp;
for(i = 0; *p; p++) {
path[i++] = tolower(*p);
}
path[i++] = '\0';
// Find the length of the common prefix
int com;
for(com = 0; base[com] && path[com]; com++) {
if(base[com] != path[com]) break;
}
if(!(base[com] && path[com])) return; // weird, prefix is entire string
if(com == 0) return; // maybe on different drive letters?
int sections = 0;
int secLen = 0, secStart = 0;
for(i = com; base[i]; i++) {
if(base[i] == '/' || base[i] == '\\') {
if(secLen == 2 && memcmp(base+secStart, "..", 2)==0) return;
if(secLen == 1 && memcmp(base+secStart, ".", 1)==0) return;
sections++;
secLen = 0;
secStart = i+1;
} else {
secLen++;
}
}
// For every directory in the prefix of the base, we must go down a
// directory in the relative path name
strcpy(out, "");
for(i = 0; i < sections; i++) {
strcat(out, "../");
}
strcat(out, path+com);
strcpy(pathp, out);
}
void MakePathAbsolute(char *basep, char *pathp) {
char out[MAX_PATH];
strcpy(out, basep);
// Chop off the filename
int i;
for(i = strlen(out) - 1; i >= 0; i--) {
if(out[i] == '\\' || out[i] == '/') break;
}
if(i < 0) return; // base is not an absolute path, or something?
out[i+1] = '\0';
strcat(out, pathp);
GetAbsoluteFilename(out);
strcpy(pathp, out);
}
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
double a21, double a22, double a23, double a24, double a21, double a22, double a23, double a24,
double a31, double a32, double a33, double a34, double a31, double a32, double a33, double a34,

View File

@ -63,8 +63,15 @@ void Error(char *str, ...)
vsprintf(buf, str, f); vsprintf(buf, str, f);
va_end(f); va_end(f);
EnableWindow(GraphicsWnd, FALSE);
EnableWindow(TextWnd, FALSE);
HWND h = GetForegroundWindow(); HWND h = GetForegroundWindow();
MessageBox(h, buf, "SolveSpace Error", MB_OK | MB_ICONERROR); MessageBox(h, buf, "SolveSpace Error", MB_OK | MB_ICONERROR);
EnableWindow(TextWnd, TRUE);
EnableWindow(GraphicsWnd, TRUE);
SetForegroundWindow(GraphicsWnd);
} }
void ExitNow(void) { void ExitNow(void) {
@ -696,9 +703,14 @@ BOOL GetOpenFile(char *file, char *defExtension, char *selPattern)
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
EnableWindow(GraphicsWnd, FALSE); EnableWindow(GraphicsWnd, FALSE);
EnableWindow(TextWnd, FALSE);
BOOL r = GetOpenFileName(&ofn); BOOL r = GetOpenFileName(&ofn);
EnableWindow(TextWnd, TRUE);
EnableWindow(GraphicsWnd, TRUE); EnableWindow(GraphicsWnd, TRUE);
SetForegroundWindow(GraphicsWnd); SetForegroundWindow(GraphicsWnd);
return r; return r;
} }
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern) BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
@ -716,19 +728,38 @@ BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
EnableWindow(GraphicsWnd, FALSE); EnableWindow(GraphicsWnd, FALSE);
EnableWindow(TextWnd, FALSE);
BOOL r = GetSaveFileName(&ofn); BOOL r = GetSaveFileName(&ofn);
EnableWindow(TextWnd, TRUE);
EnableWindow(GraphicsWnd, TRUE); EnableWindow(GraphicsWnd, TRUE);
SetForegroundWindow(GraphicsWnd); SetForegroundWindow(GraphicsWnd);
return r; return r;
} }
int SaveFileYesNoCancel(void) int SaveFileYesNoCancel(void)
{ {
return MessageBox(GraphicsWnd, EnableWindow(GraphicsWnd, FALSE);
EnableWindow(TextWnd, FALSE);
int r = MessageBox(GraphicsWnd,
"The program has changed since it was last saved.\r\n\r\n" "The program has changed since it was last saved.\r\n\r\n"
"Do you want to save the changes?", "SolveSpace", "Do you want to save the changes?", "SolveSpace",
MB_YESNOCANCEL | MB_ICONWARNING); MB_YESNOCANCEL | MB_ICONWARNING);
}
EnableWindow(TextWnd, TRUE);
EnableWindow(GraphicsWnd, TRUE);
SetForegroundWindow(GraphicsWnd);
return r;
}
void GetAbsoluteFilename(char *file)
{
char absoluteFile[MAX_PATH];
GetFullPathName(file, sizeof(absoluteFile), absoluteFile, NULL);
strcpy(file, absoluteFile);
}
static void MenuById(int id, BOOL yes, BOOL check) static void MenuById(int id, BOOL yes, BOOL check)
{ {
@ -933,13 +964,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
s = strrchr(file, '"'); s = strrchr(file, '"');
if(s) *s = '\0'; if(s) *s = '\0';
} }
char absoluteFile[MAX_PATH] = "";
if(*file != '\0') { if(*file != '\0') {
GetFullPathName(file, sizeof(absoluteFile), absoluteFile, NULL); GetAbsoluteFilename(file);
} }
// Call in to the platform-independent code, and let them do their init // Call in to the platform-independent code, and let them do their init
SS.Init(absoluteFile); SS.Init(file);
ShowWindow(TextWnd, SW_SHOWNOACTIVATE); ShowWindow(TextWnd, SW_SHOWNOACTIVATE);
ShowWindow(GraphicsWnd, SW_SHOW); ShowWindow(GraphicsWnd, SW_SHOW);

View File

@ -5,7 +5,6 @@ DXF export
TTF font text TTF font text
some kind of rounding / chamfer some kind of rounding / chamfer
remove back button in browser? remove back button in browser?
relative paths for import
auto-generate circles and faces when lathing auto-generate circles and faces when lathing
copy the section geometry to other end when sweeping copy the section geometry to other end when sweeping
cylindrical faces cylindrical faces