@@ -161,6 +161,31 @@ std::function<void()> _onWindowMoved;
161161
162162namespace Processing {
163163
164+ static FILE * processingOpenFile (const char * path, const char * mode) {
165+ #ifdef _WIN32
166+ FILE * file = nullptr ;
167+ return ::fopen_s (&file, path, mode) == 0 ? file : nullptr ;
168+ #else
169+ return ::fopen (path, mode);
170+ #endif
171+ }
172+
173+ static FILE * processingOpenPipe (const char * command, const char * mode) {
174+ #ifdef _WIN32
175+ return ::_popen (command, mode);
176+ #else
177+ return ::popen (command, mode);
178+ #endif
179+ }
180+
181+ static int processingClosePipe (FILE * pipe) {
182+ #ifdef _WIN32
183+ return ::_pclose (pipe);
184+ #else
185+ return ::pclose (pipe);
186+ #endif
187+ }
188+
164189static void _doEnableDebugConsole () {
165190#ifdef _WIN32
166191 if (AllocConsole ()) {
@@ -2550,7 +2575,9 @@ PImage* PApplet::loadImage(const ::std::string& path){
25502575 // Handle URLs: download with curl/wget and validate image magic bytes
25512576 if (path.size ()>7 && (path.substr (0 ,7 )==" http://" || path.substr (0 ,8 )==" https://" )){
25522577#ifdef _WIN32
2553- ::std::string tmp=::std::string (getenv (" TEMP" )?getenv (" TEMP" ):" C:\\ Temp" )+" \\ pg_img_" ;
2578+ ::std::string tempDir = processingEnvironmentVariable (" TEMP" );
2579+ if (tempDir.empty ()) tempDir = " C:\\ Temp" ;
2580+ ::std::string tmp=tempDir+" \\ pg_img_" ;
25542581#else
25552582 ::std::string tmp=" /tmp/pg_img_" ;
25562583#endif
@@ -2561,7 +2588,7 @@ PImage* PApplet::loadImage(const ::std::string& path){
25612588 for (char & c:bn) if (c==' :' ||c==' *' ||c==' <' ||c==' >' ||c==' |' ) c=' _' ;
25622589 tmp+=bn;
25632590 auto isValidImg=[&]()->bool {
2564- FILE * f2=fopen (tmp.c_str ()," rb" ); if (!f2) return false ;
2591+ FILE * f2=processingOpenFile (tmp.c_str ()," rb" ); if (!f2) return false ;
25652592 fseek (f2,0 ,SEEK_END ); long sz=ftell (f2); fseek (f2,0 ,SEEK_SET );
25662593 unsigned char h[4 ]={}; fread (h,1 ,4 ,f2); fclose (f2);
25672594 if (sz<100 ) return false ;
@@ -2594,9 +2621,8 @@ PImage* PApplet::loadImage(const ::std::string& path){
25942621 }
25952622 // Search paths: current dir, data/, files/, and sketch subdirs
25962623 // Check PROCESSING_SKETCH_PATH env var set by IDE
2597- ::std::string _sketchDir;
2598- if (const char * _sp = ::std::getenv (" PROCESSING_SKETCH_PATH" ))
2599- _sketchDir = ::std::string (_sp) + " /" ;
2624+ ::std::string _sketchDir = processingEnvironmentVariable (" PROCESSING_SKETCH_PATH" );
2625+ if (!_sketchDir.empty ()) _sketchDir += " /" ;
26002626 // Also get the directory of the running executable
26012627 ::std::string _exeDir;
26022628 {
@@ -3622,22 +3648,22 @@ void PApplet::run(){
36223648 {
36233649 ::std::string _homeDir;
36243650#ifdef _WIN32
3625- if ( const char * h = :: std::getenv (" USERPROFILE" )) _homeDir = h ;
3651+ _homeDir = processingEnvironmentVariable (" USERPROFILE" );
36263652#else
3627- if ( const char * h = :: std::getenv (" HOME" )) _homeDir = h ;
3653+ _homeDir = processingEnvironmentVariable (" HOME" );
36283654#endif
36293655 ::std::string _modePath;
3630- if ( const char * mp = :: std::getenv (" PROCESSING_MODE_PATH" ))
3631- _modePath = :: std::string (mp) + " /" ;
3656+ _modePath = processingEnvironmentVariable (" PROCESSING_MODE_PATH" );
3657+ if (! _modePath. empty ()) _modePath += " /" ;
36323658
36333659 // Font name used by Processing4
36343660 const ::std::string _font = " ProcessingSansPro-Regular.ttf" ;
36353661
36363662 // Check Documents/Processing on Windows (user sketchbook)
36373663 ::std::string _docsPath;
36383664#ifdef _WIN32
3639- if ( const char * ud = ::std::getenv (" USERPROFILE" ))
3640- _docsPath = :: std::string (ud) + " /Documents/Processing/" ;
3665+ ::std::string userProfile = processingEnvironmentVariable (" USERPROFILE" );
3666+ if (!userProfile. empty ()) _docsPath = userProfile + " /Documents/Processing/" ;
36413667#endif
36423668
36433669 if (!tryLoadTTF (" fonts/" + _font, g_textSize) &&
@@ -4479,7 +4505,7 @@ static PShape* svgLoad(const ::std::string& path){
44794505 // Search paths
44804506 ::std::vector<::std::string> tries={path," data/" +path," files/" +path};
44814507 ::std::string found;
4482- for (auto & t:tries){FILE * f=fopen (t.c_str ()," r" );if (f){fclose (f);found=t;break ;}}
4508+ for (auto & t:tries){FILE * f=processingOpenFile (t.c_str ()," r" );if (f){fclose (f);found=t;break ;}}
44834509 if (found.empty ()){::std::cerr<<" loadShape: file not found: " <<path<<" \n " ;return new PShape ();}
44844510
44854511 ::std::ifstream f (found);
@@ -4681,7 +4707,7 @@ static ::std::unordered_map<::std::string,GLuint> objLoadMtl(const ::std::string
46814707static PShape* objLoad (const ::std::string& path){
46824708 ::std::vector<::std::string> tries={path," data/" +path," files/" +path};
46834709 ::std::string found;
4684- for (auto & t:tries){FILE * f2=fopen (t.c_str ()," r" );if (f2){fclose (f2);found=t;break ;}}
4710+ for (auto & t:tries){FILE * f2=processingOpenFile (t.c_str ()," r" );if (f2){fclose (f2);found=t;break ;}}
46854711 if (found.empty ()){::std::cerr<<" loadShape: OBJ not found: " <<path<<" \n " ;return new PShape ();}
46864712
46874713 // Get directory for relative texture paths
@@ -5007,7 +5033,7 @@ PFont* PApplet::createFont(const ::std::string& name, float size, bool /*smooth*
50075033 // Also search system font dirs recursively (Linux: fc-list output)
50085034 #ifndef _WIN32
50095035 {
5010- FILE * fc = popen ((" fc-list : file | grep -i '" + nameNoExt + " ' | head -5" ).c_str (), " r" );
5036+ FILE * fc = processingOpenPipe ((" fc-list : file | grep -i '" + nameNoExt + " ' | head -5" ).c_str (), " r" );
50115037 if (fc) {
50125038 char buf[512 ];
50135039 while (fgets (buf, sizeof (buf), fc)) {
@@ -5022,7 +5048,7 @@ PFont* PApplet::createFont(const ::std::string& name, float size, bool /*smooth*
50225048 if (!fpath.empty ()) paths.push_back (fpath);
50235049 }
50245050 }
5025- pclose (fc);
5051+ processingClosePipe (fc);
50265052 }
50275053 }
50285054 #endif
@@ -5078,26 +5104,26 @@ ::std::string PApplet::selectInput(const ::std::string& prompt,const ::std::stri
50785104 (void )prompt; return " " ;
50795105#endif
50805106 ::std::string cmd=" zenity --file-selection --title=\" " +prompt+" \" 2>/dev/null" ;
5081- FILE * p=popen (cmd.c_str ()," r" ); if (!p)return " " ;
5082- char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); pclose (p);
5107+ FILE * p=processingOpenPipe (cmd.c_str ()," r" ); if (!p)return " " ;
5108+ char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); processingClosePipe (p);
50835109 ::std::string r (buf); if (!r.empty ()&&r.back ()==' \n ' )r.pop_back (); return r;
50845110}
50855111::std::string PApplet::selectOutput (const ::std::string& prompt,const ::std::string&){
50865112#ifdef __EMSCRIPTEN__
50875113 (void )prompt; return " " ;
50885114#endif
50895115 ::std::string cmd=" zenity --file-selection --save --title=\" " +prompt+" \" 2>/dev/null" ;
5090- FILE * p=popen (cmd.c_str ()," r" ); if (!p)return " " ;
5091- char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); pclose (p);
5116+ FILE * p=processingOpenPipe (cmd.c_str ()," r" ); if (!p)return " " ;
5117+ char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); processingClosePipe (p);
50925118 ::std::string r (buf); if (!r.empty ()&&r.back ()==' \n ' )r.pop_back (); return r;
50935119}
50945120::std::string PApplet::selectFolder (const ::std::string& prompt){
50955121#ifdef __EMSCRIPTEN__
50965122 (void )prompt; return " " ;
50975123#endif
50985124 ::std::string cmd=" zenity --file-selection --directory --title=\" " +prompt+" \" 2>/dev/null" ;
5099- FILE * p=popen (cmd.c_str ()," r" ); if (!p)return " " ;
5100- char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); pclose (p);
5125+ FILE * p=processingOpenPipe (cmd.c_str ()," r" ); if (!p)return " " ;
5126+ char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); processingClosePipe (p);
51015127 ::std::string r (buf); if (!r.empty ()&&r.back ()==' \n ' )r.pop_back (); return r;
51025128}
51035129
@@ -5111,9 +5137,8 @@ PImage* PApplet::requestImage(const ::std::string& path){
51115137 ::std::thread ([img, path]{
51125138 // Resolve search paths same as loadImage
51135139 // Check PROCESSING_SKETCH_PATH env var set by IDE
5114- ::std::string _sketchDir;
5115- if (const char * _sp = ::std::getenv (" PROCESSING_SKETCH_PATH" ))
5116- _sketchDir = ::std::string (_sp) + " /" ;
5140+ ::std::string _sketchDir = processingEnvironmentVariable (" PROCESSING_SKETCH_PATH" );
5141+ if (!_sketchDir.empty ()) _sketchDir += " /" ;
51175142 // Also get the directory of the running executable
51185143 ::std::string _exeDir;
51195144 {
@@ -5139,7 +5164,7 @@ PImage* PApplet::requestImage(const ::std::string& path){
51395164 };
51405165 ::std::string found;
51415166 for (auto & t : tries) {
5142- FILE * f = fopen (t.c_str (), " rb" );
5167+ FILE * f = processingOpenFile (t.c_str (), " rb" );
51435168 if (f) { fclose (f); found = t; break ; }
51445169 }
51455170 if (found.empty ()) {
@@ -5248,8 +5273,8 @@ PImage getRegion(int x,int y,int w,int h){
52485273
52495274::std::vector<::std::string> PApplet::loadStrings (const ::std::string& path) {
52505275 ::std::vector<::std::string> lines;
5251- ::std::string sketchDir;
5252- if (const char * sp = :: std::getenv ( " PROCESSING_SKETCH_PATH " )) sketchDir = :: std::string (sp) + " /" ;
5276+ ::std::string sketchDir = processingEnvironmentVariable ( " PROCESSING_SKETCH_PATH " ) ;
5277+ if (!sketchDir. empty ( )) sketchDir += " /" ;
52535278 ::std::ifstream f (path);
52545279 if (!f) f.open (sketchDir + path);
52555280 if (!f) f.open (sketchDir + " data/" + path);
0 commit comments