File oooqs-1.0_rc3-quickstart.patch of Package OpenOffice_org-Quickstarter

--- oooqs/oooqs.cpp
+++ oooqs/oooqs.cpp
@@ -18,6 +18,11 @@
 #include "oooqs.h"
 #include <prefsdialog.h>
 
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+
 #include <qcursor.h>
 #include <qfile.h>
 #include <qiodevice.h>
@@ -148,12 +153,13 @@
 	else
 		instance << soffice << "-quickstart";
 
+	/** Make sure that instance is automatically restarted when it gets closed */
+	connect(&instance, SIGNAL (processExited(KProcess*)), SLOT (restartOfficeWait()));
+
 	/** Check if the quickstart should be enabled */
 	if (quickstartEnabled){
-		/** Make sure that instance is automatically restarted when it gets closed */
-		connect(&instance, SIGNAL (processExited(KProcess*)), SLOT (restartOffice()));
 		/** Try to start instance for the first time */
-		restartOffice();
+		restartOffice(true);
 	}
 }
 
@@ -229,14 +235,37 @@
 	startInstances("private:factory/swriter/web");
 }
 
+/** Restarts OpenOffice if removed from memory and try to wait if an other OOo isntance is already running */
+void OooQs::restartOfficeWait(){
+	restartOffice(false);
+}
+
 /** Restarts OpenOffice if removed from memory. */
-void OooQs::restartOffice(){
+void OooQs::restartOffice(bool immediately){
 	/** at first check if the quickstart-mode is enabled */
 	if (quickstartEnabled){
 		/** check, if the Master Instance is running ! */
 		if (!instance.isRunning()) {
-			/** we dont need any Communication ! */
-			instance.start(KProcess::NotifyOnExit,KProcess::NoCommunication);
+		        if (!immediately) {
+				int waitSec=120;
+		    		while ((isAnotherOOoInstanceRunning()) && (--waitSec >= 0))
+				sleep(1);
+			}
+			if (!isAnotherOOoInstanceRunning()) {
+				/** we dont need any Communication ! */
+				instance.start(KProcess::NotifyOnExit,KProcess::NoCommunication);
+			} else {
+				/** another OOo isntance is running then each new OOo instance
+				    will be immediately exited, so the quickstarter mode will not
+				    work and must be disabled */
+				KMessageBox::information(preferencesDialog, i18n("The quickstart mode cannot be enabled at this time because OpenOffice.org is already in use.\n"
+				                                                 "\n"
+										 "You can enable the quickstart mode in the Quickstarter configuration dialog after you have stopped the current OpenOffice.org."));
+				preferencesDialog->enableQuick->setChecked(false);
+				quickstartEnabled=false;
+				/** save changed value into the config file */
+				changedConfig();
+			}	    
 		}
 	}
 }
@@ -324,13 +353,13 @@
 		if (quickstartEnabled){
 			quickstartEnabled=false;
 			if (instance.isRunning()){
-				if (KMessageBox::questionYesNo(0, i18n("There is still a quickstart-instance of %1 running.\nDo you want to kill it now?\n\nMake sure you close all your %2 documents before answering yes!").arg(suite).arg(suite), i18n("Running instance of %1 detected").arg(suite)) == 3){
+				if (KMessageBox::questionYesNo(preferencesDialog, i18n("There is still a quickstart-instance of %1 running.\nDo you want to kill it now?\n\nMake sure you close all your %2 documents before answering yes!").arg(suite).arg(suite), i18n("Running instance of %1 detected").arg(suite)) == 3){
 					instance.kill();
 				}
 			}
 		}else{
 			quickstartEnabled=true;
-			restartOffice();
+			restartOffice(true);
 		}
 	}
 	if (open){
@@ -744,3 +773,135 @@
 QString OooQs::getSoffice(void){
 	return soffice;
 }
+
+/** helper function for the function scandir
+    we are interested in directories with informations about processes */
+int procSelect(const struct dirent *dirEnt)
+{
+	/** is it directory? */
+	if (dirEnt->d_type == DT_DIR) {
+		/** is it directory with informations about a process? */
+		char *endPtr;
+		strtol(dirEnt->d_name, &endPtr, 10);
+		if (*endPtr == '\0')
+    			/** yes, it is */
+    			return 1;
+	}
+	/** non-interesting dir entry */
+	return 0;
+}
+
+#define OooQs_SERACH_FILE_BUFFER_STEP 10000
+
+/** search file for the string */
+int OooQs::searchFile(const char *path, const char *string)
+{
+	FILE *file;
+	char *buf, *pBuf;
+	int bufSize=0;
+	int read;
+  
+	/** open the file for reading */
+	if(!(file = fopen(path, "r")))
+		/** probably we have not rights to read this file, but in this case
+    		    the file is not interesting for us */
+		return 0;
+  
+	/** read the whole file in a buffer */
+	/** unfortunatelly the fseek does not work in the proc file system,
+            so it is not possible to discover the file size */
+	if (!(buf=(char *)malloc(OooQs_SERACH_FILE_BUFFER_STEP))) {
+		fclose(file);
+		return 0;
+	}
+	bufSize=OooQs_SERACH_FILE_BUFFER_STEP;
+	pBuf=buf;
+	while ((read=fread(pBuf, 1, OooQs_SERACH_FILE_BUFFER_STEP, file)) == OooQs_SERACH_FILE_BUFFER_STEP) {
+		bufSize += OooQs_SERACH_FILE_BUFFER_STEP;
+		if(!(buf = (char *)realloc(buf, bufSize))) {
+    			fclose(file);
+    			return 0;
+		}
+		/** the pBuf must be derived from the new buf (after realloc) !!! */
+		pBuf = buf + bufSize - OooQs_SERACH_FILE_BUFFER_STEP;
+	}
+  
+	/** close the file */
+	fclose(file);
+
+	/** add '\0' at the end of read string */
+	pBuf = &(buf[bufSize - OooQs_SERACH_FILE_BUFFER_STEP + read]);
+	*pBuf='\0';
+	/** file environ contains many '\0'. change them to '.', so
+    	    strstr can be used */
+	while (--pBuf >= buf)
+		if (*pBuf == '\0')
+    			*pBuf='.';
+  
+	/** try to find the string in the buffer */
+	if(strstr(buf, string)) {
+		/** string found */
+		free(buf);
+		return 1;
+	}
+      
+	/** string not found */
+	free(buf);
+	return 0;
+}
+
+/** free the array with dir entries allocated by the function scandir */
+void OooQs::freeDirList(struct dirent **dirList, int dirEntNum)
+{
+	for (int i = 0; i < dirEntNum; i++) {
+		free(dirList[i]);
+	}
+	
+	if (dirList) free(dirList);
+}
+
+/** check if the soffice.bin is runnig by the user $USER */
+int OooQs::isAnotherOOoInstanceRunning()
+{
+	struct dirent **procList=NULL;
+	int dirEntNum;
+	int i;
+	char searchedUSER[1024];
+	char searchedFile[1024];
+
+	/** which user is running this Quickstarter instance */
+	strcpy(searchedUSER, "USER=");
+	strncat(searchedUSER, getenv("USER"), 1000);
+
+	/** scan the directory /proc for directories with informations about processes */
+	dirEntNum = scandir("/proc", &procList, &procSelect, &alphasort);   
+  
+	if(dirEntNum < 0)
+		/** the /proc dir can not be read */
+		return 0;
+
+	/** scan each process */
+	for(i = 0; i < dirEntNum; i++) {
+		strcpy(searchedFile, "/proc/");
+		strncat(searchedFile, procList[i]->d_name, 1000);
+		strcat(searchedFile, "/cmdline");
+
+		/** does it run soffice.bin? */
+		if(searchFile(searchedFile, "soffice.bin")) {
+    			strcpy(searchedFile, "/proc/");
+    			strncat(searchedFile, procList[i]->d_name, 1000);
+    			strcat(searchedFile, "/environ");
+
+    			/** does it run the user $USER? */
+    			if(searchFile(searchedFile, searchedUSER)) {
+    				/** yes, it does. Another OOo instance is already running */
+    				freeDirList(procList, dirEntNum);
+				return 1;
+    			}
+		}
+	}
+  
+	/** no other running OOo instance found */
+	freeDirList(procList, dirEntNum);
+	return 0;
+}
--- oooqs/oooqs.h
+++ oooqs/oooqs.h
@@ -128,8 +128,8 @@
 	void startWriter();
 	/** Executes the about-dialog. */
 	void showAbout();
-	/** Restarts OpenOffice if removed from memory. */
-	void restartOffice();
+	/** Restarts OpenOffice if removed from memory and try to wait if an other OOo isntance is already running. */
+	void restartOfficeWait();
 	/** Delete the process. */
 	void delProcess(KProcess* process);
 	/** Call this to open the start-dialog. */
@@ -149,6 +149,14 @@
 	void setDoubleClickAction();
 	/** Set the texts on the actions opening the connected module. */
 	void updateActions(void);
+	/** Restarts OpenOffice if removed from memory. */
+	void restartOffice(bool immediately);
+	/** search file for the string */
+	int searchFile(const char *path, const char *string);
+	/** free the array with dir entries allocated by the function scandir */
+	void freeDirList(struct dirent **dirList, int dirEntNum);
+	/** check if the soffice.bin is runnig by the user $USER */
+	int isAnotherOOoInstanceRunning();
 signals:
 	/** Emit when a double click was registered */
 	void doubleClick();
openSUSE Build Service is sponsored by