1 /*
2     Copyright 2007, 2008, 2009, 2010 Geyer Klaus
3 
4     This file is part of Cat'sEyE.
5 
6     Cat'sEyE is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     Cat'sEyE is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with Cat'sEyE.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <stdlib.h>
21 #include <gtk/gtk.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 
26 #include "Lists.h"
27 #include "confighandling.h"
28 #include "confighandlingDefinitions.h"
29 #include "userdata.h"
30 #include "CommandParser.h"
31 #include "helpers.h"
32 #include "DragnDrop.h"
33 #include "threads.h"
34 #include "mytrace.h"
35 #include "myfm.h"
36 #include "globalDefinitions.h"
37 
38 #include "allInclude.h"
39 
40 void CallUserCommand_MainEntryThread (void *data);
41 int CallUserCommand_StartThreadStructure_freeStruct (struct _CallUserCommand_StartThreadStructure **ThreadStartStruct);
42 int CallUserCommand_CallToSystem (void *data);
43 int CallUserCommand_ProcessViaList(struct _CallUserCommand_StartThreadStructure *ThreadStartStruct);
44 int CallUserCommand_ParseCommand(struct _CallUserCommand_StartThreadStructure *ThreadStartStruct);
45 
46 
47 extern GtkWindow 		*win;
48 
49 extern struct _OptionsList *g_OptionsList;
50 extern struct _OptionsList *g_BookMarkList;
51 
52 
UserCommand_CreateUserMenu(GtkWidget * rootmenu,struct UserDataList * UserData,struct MenuObjectList ** MenuObjects)53 void UserCommand_CreateUserMenu(GtkWidget *rootmenu, struct UserDataList *UserData, struct MenuObjectList **MenuObjects){
54     //in, in, out
55     //!do not forget to free the MenuObjects LIST !!!!!!!!!!!!!!!!!!!!!!!!
56     //mind, that USerData->UserCommandName is changed in here!
57 
58 	TRACEIT(10,"UserCommand_CreateUserMenu		start");
59 
60 	UserData = UserDataList_getFirstItem (UserData);
61 
62 	if (rootmenu == NULL || UserData == NULL || MenuObjects == NULL){
63         TRACEIT (2, "UserCommand_CreateUserMenu             end, parameter NULL");
64         return;
65 	}
66 
67 	const char sep[] = "/";
68 	char *buf;
69 	int found = 0;
70 	int werehere = 0;
71 	GString *gstrName = g_string_sized_new(10);
72 	GString *gstrPath = g_string_sized_new(10);
73 	GtkWidget *LastMenu = NULL;
74 	GtkWidget *MenuBuf = NULL;
75 	struct MenuObjectList *MenuObjectsBuf=NULL;
76 
77 	//Create MenuStructure internal
78 	while (UserData && UserData->gstrMenuName){
79 	    //overwrite the menuname with the completeName (for the bookmarks)
80         if (UserData->gstrMenuName && UserData->gstrCompleteName){
81             g_string_assign (UserData->gstrMenuName, UserData->gstrCompleteName->str);
82         }
83 
84 	    g_string_assign(gstrName, UserData->gstrMenuName->str);
85 	    cutCharFromGString(gstrName, '/',1); //cut leading /
86 		if(strstr(gstrName->str,sep) != NULL){
87 			g_string_assign(gstrPath, UserData->gstrMenuName->str);
88 			GetPathFromPathWithName(gstrPath, 1);
89 			getLastStringInPath(gstrName);
90 
91 			LastMenu = rootmenu;
92 			werehere = 0;
93 			for (buf = strtok(gstrPath->str,sep); buf; buf=strtok(NULL,sep)){
94 				werehere = 1;
95 				if (*MenuObjects != NULL)
96                     MenuObjectsBuf = MenuObjectList_getFirstItem(*MenuObjects);
97                 else
98                     MenuObjectsBuf = NULL;
99 				found = 0;
100 				while (MenuObjectsBuf){
101 					if (strcmp (MenuObjectsBuf->gstrName->str, buf) == 0 && MenuObjectsBuf->MenuToAddTo == LastMenu){
102 						found = 1;
103 						MenuBuf = MenuObjectsBuf->submenu;
104 						LastMenu = MenuBuf;
105 						break;
106 					}
107 					MenuObjectsBuf = MenuObjectsBuf->nextItem;
108 				}
109 				if (found != 1){
110 				    //printf("UserCommand_CreateUserMenu      new menu with name: %s\n",buf);
111 					MenuBuf = gtk_menu_new();
112 					MenuObjectList_AddItem(MenuObjects, buf, MenuBuf, LastMenu);
113 					LastMenu = MenuBuf;
114 				}
115 			}
116 			if (werehere != 0){
117 				g_string_assign(UserData->gstrMenuName, gstrName->str);
118 				UserData->MenuToAddTo = MenuBuf;
119 			}
120 		}
121 		if (UserData->MenuToAddTo == NULL){
122 			UserData->MenuToAddTo = rootmenu;
123 		}
124 		UserData = UserData->nextItem;
125 	}
126 	g_string_free(gstrName, TRUE);
127 	g_string_free(gstrPath, TRUE);
128 	TRACEIT(10,"UserCommand_CreateUserMenu		end");
129 }
130 
131 
UserCommand_AttachUserMenu(struct MenuObjectList * MenuObjects)132 void UserCommand_AttachUserMenu(struct MenuObjectList *MenuObjects){
133 	TRACEIT(10,"UserCommand_AttachUserMenu		start");
134 	GtkWidget *MenuBuf = NULL;
135 
136 	//Now create Menustructure for viewing
137 	MenuObjects = MenuObjectList_getFirstItem(MenuObjects);
138 	if (MenuObjects == NULL){
139         TRACEIT (2, "UserCommand_AttachUserMenu         end, parameter NULL");
140         return;
141 	}
142 
143 	while (MenuObjects){
144 		MenuBuf = gtk_menu_item_new_with_label(MenuObjects->gstrName->str);
145 		gtk_menu_item_set_submenu ((GtkMenuItem *)MenuBuf,MenuObjects->submenu);
146 		gtk_menu_shell_append(GTK_MENU_SHELL(MenuObjects->MenuToAddTo), MenuBuf);
147 		MenuObjects = MenuObjects->nextItem;
148 	}
149 	TRACEIT(10,"UserCommand_AttachUserMenu		end");
150 }
151 
152 /////////////////////////////////////////////////////////////////////////////////////////////////
153 ///////////////// USER DATA LIST //////////////////////////////////////////////////////////////
154 /////////////////////////////////////////////////////////////////////////////////////////////////
155 
UserDataList_AddItem(struct UserDataList ** theList,char * cpCompleteName,void * ListElement)156 void UserDataList_AddItem(struct UserDataList **theList, char *cpCompleteName, void *ListElement){
157 	TRACEIT(10,"UserDataList_AddItem			start");
158 	if (theList == NULL || cpCompleteName == NULL){
159 	    TRACEIT(2,"UserDataList_AddItem			end, Parameter NULL");
160 		return;
161 	}
162 	struct UserDataList *NewItem=NULL;
163 	struct UserDataList *bufItem=NULL;
164 
165 	NewItem = malloc (sizeof (struct UserDataList));
166 
167 	if (NULL == NewItem){
168 		TRACEIT(1,"UserDataList_AddItem			end, Error allocating memory");
169 		return;
170 	}
171 
172     NewItem->iSourceType = -1;
173     NewItem->Object = NULL;
174     NewItem->gstrCompleteName = g_string_new (cpCompleteName);
175     NewItem->gstrMenuName = g_string_new(cpCompleteName);
176     NewItem->ListElement = ListElement;
177     NewItem->MenuToAddTo = NULL;
178     NewItem->prevItem = NULL;
179     NewItem->nextItem = NULL;
180 
181     if (*theList == NULL){
182         *theList = NewItem;
183         //printf ("new List: %p\n", NewItem);
184     }
185     else{
186         bufItem = UserDataList_getLastItem(*theList);
187         //printf ("add to List: %p\n", *theList);
188         bufItem->nextItem = NewItem;
189         NewItem->prevItem = bufItem;
190     }
191 
192 	TRACEIT(10,"UserDataList_AddItem			end");
193 }
194 
195 
UserDataList_DeleteList(struct UserDataList ** theList)196 void UserDataList_DeleteList(struct UserDataList **theList){
197 	TRACEIT(10,"UserDataList_DeleteList			start");
198 	if (NULL == theList || *theList == NULL){
199 		TRACEIT(2,"UserDataList_DeleteList			end, parameter NULL");
200 		return;
201 	}
202 
203 	struct UserDataList *bufItem = UserDataList_getFirstItem(*theList);
204     struct UserDataList *bufItem2 = NULL;
205     //printf ("delete List: %p\n", bufItem);
206 
207     while (bufItem){
208         if (bufItem->gstrCompleteName){
209             g_string_free(bufItem->gstrCompleteName,TRUE);
210         }
211         if (bufItem->gstrMenuName){
212             g_string_free(bufItem->gstrMenuName,TRUE);
213         }
214         bufItem2 = bufItem;
215         bufItem = bufItem->nextItem;
216         free(bufItem2);
217     }
218     *theList = NULL;
219 
220 	TRACEIT(10,"UserDataList_DeleteList			end");
221 }
222 
223 
UserDataList_getStandardItem(struct UserDataList * theList)224 struct UserDataList *UserDataList_getStandardItem(struct UserDataList *theList){
225     TRACEIT(10,"UserDataList_getStandardItem			start");
226 
227     theList = UserDataList_getFirstItem (theList);
228     if (theList == NULL){
229         TRACEIT(2,"UserDataList_getStandardItem			end, parameter NULL");
230         return NULL;
231     }
232 
233     while (theList != NULL){
234         if ( ((struct _UserCommandList *)(theList->ListElement))->iIsDefaultCommand == 1){
235             return theList;
236         }
237         theList = theList->nextItem;
238     }
239 
240     TRACEIT(10,"UserDataList_getStandardItem			end");
241     return NULL;
242 }
243 
244 
UserDataList_getItemByListElement(struct UserDataList * theList,void * ListElement)245 struct UserDataList *UserDataList_getItemByListElement(struct UserDataList *theList, void *ListElement){
246     TRACEIT(10,"UserDataList_getItemByListElement			start");
247 
248     theList = UserDataList_getFirstItem (theList);
249     if (theList == NULL){
250         TRACEIT(2,"UserDataList_getItemByListElement			end, parameter NULL");
251         return NULL;
252     }
253 
254     while (theList != NULL){
255         if ( theList->ListElement == ListElement){
256             return theList;
257         }
258         theList = theList->nextItem;
259     }
260 
261     TRACEIT(10,"UserDataList_getItemByListElement			end");
262     return NULL;
263 }
264 
265 
UserDataList_getFirstItem(struct UserDataList * theList)266 struct UserDataList *UserDataList_getFirstItem(struct UserDataList *theList){
267     TRACEIT(10,"UserDataList_getFirstItem			start");
268     if (theList == NULL){
269         TRACEIT(2,"UserDataList_getFirstItem			end, parameter NULL");
270         return NULL;
271     }
272 
273     while (theList->prevItem != NULL){
274         theList = theList->prevItem;
275     }
276 
277     TRACEIT(10,"UserDataList_getFirstItem			end");
278     return theList;
279 }
280 
281 
UserDataList_getLastItem(struct UserDataList * theList)282 struct UserDataList *UserDataList_getLastItem(struct UserDataList *theList){
283     TRACEIT(10,"UserDataList_getLastItem			start");
284     if (theList == NULL){
285         TRACEIT(2,"UserDataList_getLastItem			end, parameter NULL");
286         return NULL;
287     }
288 
289     while (theList->nextItem != NULL){
290         theList = theList->nextItem;
291     }
292 
293     TRACEIT(10,"UserDataList_getLastItem			end");
294     return theList;
295 }
296 
297 
UserDataList_CreateDummyCommand(struct UserDataList * theDummyItem,const char * cpCommand,void * Object,int iSource,int iCallType)298 int UserDataList_CreateDummyCommand (struct UserDataList *theDummyItem, const char *cpCommand, void *Object, int iSource, int iCallType){
299     //this function creates a UserCommand with the given information to start it with the common functions
300     //theDummyItem has to be a valid pointer!
301     TRACEIT(10, "UserDataList_CreateDummyCommand        start");
302     if (theDummyItem==NULL || cpCommand==NULL || Object==NULL){
303         TRACEIT(2, "UserDataList_CreateDummyCommand     parameter NULL");
304         return -1;
305     }
306     GString *gstrWorkingPath = g_string_sized_new (10);
307 
308     theDummyItem->ListElement = NULL;
309     theDummyItem->gstrCompleteName = g_string_new(cpCommand);
310     theDummyItem->gstrMenuName = g_string_new(cpCommand);
311     theDummyItem->prevItem = NULL;
312     theDummyItem->nextItem = NULL;
313     theDummyItem->MenuToAddTo = NULL;
314     theDummyItem->iSourceType = iSource;
315     theDummyItem->Object = Object;
316 
317     struct _UserCommandList *UserCommandList = NULL;
318     UserCommandList_addItem(&UserCommandList, "UserDataList_CreateDummyCommand");
319     if (UserCommandList == NULL){
320         TRACEIT(4, "UserDataList_CreateDummyCommand  unable to create UserCommandList");
321         g_string_free(gstrWorkingPath, TRUE);
322         return -1;
323     }
324 
325     if (iSource == SOURCE_SIDEOBJECT){
326         g_string_assign (gstrWorkingPath, ((struct SideObjectList *)Object)->gstrPath->str);
327     }
328     else{
329         getHomeDirectory (gstrWorkingPath);
330     }
331 
332     theDummyItem->ListElement = UserCommandList;
333     UserCommandList->iValid = 1;
334     UserCommandList_editItem(UserCommandList, 0, NULL, NULL, cpCommand, iCallType, NULL, NULL, NULL, NULL, NULL, NULL, gstrWorkingPath->str);
335 
336     g_string_free(gstrWorkingPath, TRUE);
337 
338     TRACEIT(10, "UserDataList_CreateDummyCommand        end");
339     return 0;
340 }
341 
342 
343 /////////////////////////////////////////////////////////////////////////////////////////////////
344 ///////////////// MENU OBJECT LIST //////////////////////////////////////////////////////////////
345 /////////////////////////////////////////////////////////////////////////////////////////////////
346 
MenuObjectList_AddItem(struct MenuObjectList ** theList,char * Name,GtkWidget * submenu,GtkWidget * MenuToAddTo)347 void MenuObjectList_AddItem(struct MenuObjectList **theList, char *Name, GtkWidget *submenu, GtkWidget *MenuToAddTo){
348 	TRACEIT(10,"MenuObjectList_AddItem			start");
349 	if (Name == NULL || submenu == NULL || MenuToAddTo == NULL || theList == NULL){
350 		TRACEIT(2,"MenuObjectList_AddItem			end, parameter NULL ");
351 		return;
352 	}
353 
354 	struct MenuObjectList *NewItem;
355 	struct MenuObjectList *bufItem;
356 
357 	NewItem = malloc (sizeof (struct MenuObjectList));
358 
359 	if (NULL == NewItem){
360 		TRACEIT(1,"MenuObjectList_AddItem			end, error allocating memory");
361 		return;
362 	}
363 
364 	NewItem->gstrName = g_string_new(Name);
365 	NewItem->submenu = submenu;
366 	NewItem->MenuToAddTo = MenuToAddTo;
367 	NewItem->nextItem=NULL;
368 	NewItem->prevItem=NULL;
369 
370     if (*theList == NULL){
371         *theList = NewItem;
372     }
373     else{
374         bufItem = MenuObjectList_getLastItem (*theList);
375 
376         bufItem->nextItem = NewItem;
377         NewItem->prevItem = bufItem;
378     }
379 
380 	TRACEIT(10,"MenuObjectList_AddItem			end");
381 }
382 
383 
MenuObjectList_DeleteList(struct MenuObjectList ** theList)384 void MenuObjectList_DeleteList(struct MenuObjectList **theList){
385 	TRACEIT(10,"MenuObjectList_DeleteList			start");
386 
387     if (NULL == theList){
388 		TRACEIT(2,"MenuObjectList_DeleteList			end, parameter NULL");
389 		return;
390 	}
391 	struct MenuObjectList *bufItem = MenuObjectList_getFirstItem(*theList);;
392 	struct MenuObjectList *bufItem2 = NULL;
393 
394     if (bufItem == NULL){
395         TRACEIT(2, "MenuObjectList_DeleteList           WTF?");
396     }
397 
398 	while (bufItem){
399         if (bufItem->gstrName){
400             g_string_free(bufItem->gstrName, TRUE);
401         }
402 
403 	    bufItem2 = bufItem;
404         bufItem = bufItem->nextItem;
405         free (bufItem2);
406 	}
407 	*theList=NULL;
408 
409     TRACEIT(10,"MenuObjectList_DeleteList			end");
410 }
411 
412 
MenuObjectList_getFirstItem(struct MenuObjectList * theList)413 struct MenuObjectList *MenuObjectList_getFirstItem(struct MenuObjectList *theList){
414     TRACEIT(10,"MenuObjectList_getFirstItem			start");
415     if (theList == NULL){
416         TRACEIT(2,"MenuObjectList_getFirstItem			end, parameter NULL");
417         return NULL;
418     }
419 
420     while (theList->prevItem != NULL){
421         theList = theList->prevItem;
422     }
423 
424     TRACEIT(10,"MenuObjectList_getFirstItem			end");
425     return theList;
426 }
427 
428 
MenuObjectList_getLastItem(struct MenuObjectList * theList)429 struct MenuObjectList *MenuObjectList_getLastItem(struct MenuObjectList *theList){
430     TRACEIT(10,"MenuObjectList_getLastItem			start");
431     if (theList == NULL){
432         TRACEIT(2,"MenuObjectList_getLastItem			end, parameter NULL");
433         return NULL;
434     }
435 
436     while (theList->nextItem != NULL){
437         theList = theList->nextItem;
438     }
439 
440     TRACEIT(10,"MenuObjectList_getLastItem			end");
441     return theList;
442 }
443 
444 
445 /////////////////////////////////////////////////////////////////////////////////////////////////
446 ///////////////// calling usercommands  //////////////////////////////////////////////////////////////
447 /////////////////////////////////////////////////////////////////////////////////////////////////
448 
449 
CallUserCommand_StartThread(struct UserDataList * OurUserDataListItem,GList * glistItemsWithPath,GList * glistItemsWithoutPath,GString * gstrThisSidePath,GString * gstrOtherSidePath,GString * gstrLeftSidePath,GString * gstrRightSidePath,GString * gstrHomeDir)450 int CallUserCommand_StartThread (struct UserDataList *OurUserDataListItem, GList *glistItemsWithPath, GList *glistItemsWithoutPath, GString *gstrThisSidePath, GString *gstrOtherSidePath, GString *gstrLeftSidePath, GString *gstrRightSidePath, GString *gstrHomeDir){
451     //return: -1=error, 0=ok
452     //this (or the following function must take care of freeing all the items given here
453     //mind to free the ListItem member of OurUserDtaListItem, because this is a real copy of the data (but only one item)
454     //gstrThisSidePath and gstrOtherSidePath can be NULL in the case we come from a fileshelf!
455 
456     //this function will collect all the data and write it to some structure.
457     //after that it will start a thread which then will parse the command and takes control of all leading thinks
458     //including freeing the memory given to the structure including the memory allocated for the structure!
459     TRACEIT(10,"CallUserCommand_StartThread			start");
460     if (OurUserDataListItem == NULL /*|| glistItemsWithPath==NULL || glistItemsWithoutPath==NULL */|| gstrLeftSidePath==NULL || gstrRightSidePath==NULL || gstrHomeDir==NULL){
461         TRACEIT (2, "CallUserCommand_StartThread            parameter NULL");
462         return -1;
463     }
464 
465     struct _CallUserCommand_StartThreadStructure *ThreadStartStruct = malloc (sizeof (struct _CallUserCommand_StartThreadStructure));
466     if (ThreadStartStruct == NULL){
467         TRACEIT (2, "CallUserCommand_StartThread            unable to allocate memory");
468         return -1;
469     }
470 
471     int iRet=0;
472     GError *Error=NULL;
473 
474     ThreadStartStruct->OurUserDataListItem = OurUserDataListItem;
475     ThreadStartStruct->glistItemsWithPath = glistItemsWithPath;
476     ThreadStartStruct->glistItemsWithoutPath = glistItemsWithoutPath;
477     ThreadStartStruct->gstrThisSidePath = gstrThisSidePath;
478     ThreadStartStruct->gstrOtherSidePath = gstrOtherSidePath;
479     ThreadStartStruct->gstrLeftSidePath = gstrLeftSidePath;
480     ThreadStartStruct->gstrRightSidePath = gstrRightSidePath;
481     ThreadStartStruct->gstrHomeDir = gstrHomeDir;
482     ThreadStartStruct->gstrWorkingDir = NULL;
483     ThreadStartStruct->gstrParsedCommand = NULL;
484     ThreadStartStruct->gstrQuitReplyText = NULL;
485     ThreadStartStruct->gstrActionNoteText = NULL;
486     ThreadStartStruct->uiCurrentPositionInList = 0;
487     ThreadStartStruct->uiSizeOfLists = g_list_length (glistItemsWithPath);
488     ThreadStartStruct->iCancelAll = 0;  //0=continue, 1=cancel (for each and list mode)
489     ThreadStartStruct->commStru = NULL;
490     ThreadStartStruct->wdgtUserDialog = NULL;
491     ThreadStartStruct->wdgtUSerDialogMainVBox = NULL;
492     ThreadStartStruct->gcontDialogCondition = NULL;
493     ThreadStartStruct->gcontEachCondition = NULL;
494 
495     g_thread_create((GThreadFunc)CallUserCommand_MainEntryThread, (void *)ThreadStartStruct , FALSE, &Error);
496 
497     if (Error){
498         TRACEIT(4,"CallUserCommand_StartThread			error starting thread:");
499         TRACEIT(4, Error->message);
500 
501         CallUserCommand_StartThreadStructure_freeStruct ( &ThreadStartStruct);
502 
503         g_error_free(Error);
504         Error = NULL;
505         free(ThreadStartStruct);
506         iRet = -1;
507     }
508 
509     TRACEIT(10,"CallUserCommand_StartThread			end");
510     return iRet;
511 }
512 
513 
CallUserCommand_StartThreadStructure_freeStruct(struct _CallUserCommand_StartThreadStructure ** ThreadStartStruct)514 int CallUserCommand_StartThreadStructure_freeStruct (struct _CallUserCommand_StartThreadStructure **ThreadStartStruct){
515     if (ThreadStartStruct == NULL || *ThreadStartStruct==NULL){
516         TRACEIT (2, "CallUserCommand_StartThreadStructure_freeStruct        parameter NULL");
517         return -1;
518     }
519     UserCommandList_freeList ( (struct _UserCommandList **)&(((*ThreadStartStruct)->OurUserDataListItem)->ListElement));
520 
521     UserDataList_DeleteList( &((*ThreadStartStruct)->OurUserDataListItem));
522 
523     if ((*ThreadStartStruct)->glistItemsWithPath){
524         g_list_foreach((*ThreadStartStruct)->glistItemsWithPath, (GFunc) GListFreeGStrings, NULL); g_list_free((*ThreadStartStruct)->glistItemsWithPath);
525     }
526     if ((*ThreadStartStruct)->glistItemsWithoutPath){
527         g_list_foreach((*ThreadStartStruct)->glistItemsWithoutPath, (GFunc) GListFreeGStrings, NULL); g_list_free((*ThreadStartStruct)->glistItemsWithoutPath);
528     }
529 
530     if ( (*ThreadStartStruct)->gstrThisSidePath ){
531         g_string_free((*ThreadStartStruct)->gstrThisSidePath, TRUE);
532     }
533     if ( (*ThreadStartStruct)->gstrOtherSidePath ){
534         g_string_free((*ThreadStartStruct)->gstrOtherSidePath, TRUE);
535     }
536     if ( (*ThreadStartStruct)->gstrLeftSidePath ){
537         g_string_free((*ThreadStartStruct)->gstrLeftSidePath, TRUE);
538     }
539     if ( (*ThreadStartStruct)->gstrRightSidePath ){
540         g_string_free((*ThreadStartStruct)->gstrRightSidePath, TRUE);
541     }
542     if ( (*ThreadStartStruct)->gstrHomeDir ){
543         g_string_free((*ThreadStartStruct)->gstrHomeDir, TRUE);
544     }
545     if ( (*ThreadStartStruct)->gstrWorkingDir ){
546         g_string_free((*ThreadStartStruct)->gstrWorkingDir, TRUE);
547     }
548     if ( (*ThreadStartStruct)->gstrParsedCommand ){
549         g_string_free((*ThreadStartStruct)->gstrParsedCommand, TRUE);
550     }
551     if ( (*ThreadStartStruct)->gstrQuitReplyText ){
552         g_string_free((*ThreadStartStruct)->gstrQuitReplyText, TRUE);
553     }
554     if ( (*ThreadStartStruct)->gstrActionNoteText ){
555         g_string_free((*ThreadStartStruct)->gstrActionNoteText, TRUE);
556     }
557 
558     free (*ThreadStartStruct);
559     *ThreadStartStruct = NULL;
560 
561     return 0;
562 }
563 
564 
CallUserCommand_MainEntryThread(void * data)565 void CallUserCommand_MainEntryThread (void *data){
566     //this is our main entry point which is supposed to be threaded and started from CallUserCommand_StartThread
567     //data is from type struct _CallUserCommand_StartThreadStructur
568     TRACEIT(10,"CallUserCommand_MainEntryThread			start");
569 
570     if (data == NULL){
571         TRACEIT(2,"CallUserCommand_MainEntryThread			parameter NULL");
572         g_thread_exit(0);
573     }
574     struct _CallUserCommand_StartThreadStructure *ThreadStartStruct = (struct _CallUserCommand_StartThreadStructure *)data;
575     struct _UserCommandList *myUserCommandListItem = (struct _UserCommandList *)(ThreadStartStruct->OurUserDataListItem->ListElement);
576     GList       *glistBuf = NULL;
577     //GList       *glistEachThreads = NULL;
578     //GThread     *gthreadEachThread = NULL;
579     GError      *Error = NULL;
580     int         iRet = 0;
581     GMutex      *mutex=NULL;
582 
583     if (myUserCommandListItem->option_iCallType == USERCOMMAND_CALLTYPE_ALL){
584         iRet = CallUserCommand_ParseCommand (ThreadStartStruct);
585         if (iRet == 0 && ThreadStartStruct->iCancelAll == 0){
586             iRet = CallUserCommand_CallToSystem ((void *)ThreadStartStruct);
587         }
588     }
589     else if (myUserCommandListItem->option_iCallType == USERCOMMAND_CALLTYPE_EACH){
590         //this is the only case in which we have to work a little bit more in here
591         glistBuf = g_list_first(ThreadStartStruct->glistItemsWithPath);
592         while (glistBuf && ThreadStartStruct->uiCurrentPositionInList < ThreadStartStruct->uiSizeOfLists){
593             if (ThreadStartStruct->iCancelAll == 2){
594                 break;
595             }
596             iRet = CallUserCommand_ParseCommand (ThreadStartStruct);	//this is blocking call when asking the user for input
597             if (iRet == 0 && ThreadStartStruct->iCancelAll == 0){
598                 if (ThreadStartStruct->gcontEachCondition != NULL){
599                     TRACEIT (2, "CallUserCommand_MainEntryThread        internal error, CallUserCommand_MainEntryThread != NULL");
600                     g_cond_wait (ThreadStartStruct->gcontEachCondition, mutex);
601                 }
602                 mutex = g_mutex_new();
603                 ThreadStartStruct->gcontEachCondition = g_cond_new ();
604                 g_mutex_lock (mutex);
605 
606                 //gthreadEachThread = g_thread_create((GThreadFunc)CallUserCommand_CallToSystem, (void *)ThreadStartStruct , TRUE, &Error);
607                 g_thread_create((GThreadFunc)CallUserCommand_CallToSystem, (void *)ThreadStartStruct , FALSE, &Error);
608 				//we have to wait for this thread till condition signal because of our ThreadStartStruct, which is used for the next item too!
609                 g_cond_wait (ThreadStartStruct->gcontEachCondition, mutex);
610                 g_mutex_unlock (mutex);
611                 g_mutex_free (mutex);
612                 mutex = NULL;
613                 g_cond_free (ThreadStartStruct->gcontEachCondition);
614                 ThreadStartStruct->gcontEachCondition = NULL;
615             }
616             if (Error != NULL){
617                 TRACEIT (4, "CallUserCommand_MainEntryThread        error creating thread to call usercommand, error:");
618                 TRACEIT (4, Error->message);
619                 g_error_free(Error);
620                 Error = NULL;
621             }
622             //if (/*iRet == 0 && ThreadStartStruct->iCancelAll == 0 && */gthreadEachThread != NULL){
623             //    glistEachThreads = g_list_prepend (glistEachThreads, (void *)gthreadEachThread);
624             //    gthreadEachThread = NULL;
625             //}
626 
627             glistBuf = glistBuf->next;
628             ThreadStartStruct->uiCurrentPositionInList++;
629         }
630         //we have to wait for the threads to finish
631         //do we really have to wait for all the threads to finish? Actually, CallUserCOmmandCallToSystem
632         //will block us with a condition until it does not need the ThreadStartStruct any more, and therefore,
633         //deleting this struct should be of no harm.
634         /*
635         glistBuf = glistEachThreads;
636         while (glistBuf){
637         	printf("Joining thread      at CallUserCommand_MainEntryThread\n");
638             g_thread_join ( (GThread *)glistBuf->data);
639             printf("Leaving thread join at CallUserCommand_MainEntryThread\n");
640             glistBuf = glistBuf->next;
641         }*/
642     }
643     else if (myUserCommandListItem->option_iCallType == USERCOMMAND_CALLTYPE_LIST){
644         mutex = g_mutex_new();
645         ThreadStartStruct->gcontDialogCondition = g_cond_new ();
646         g_mutex_lock (mutex);
647 
648         CallUserCommand_ProcessViaList(ThreadStartStruct);
649 
650         g_cond_wait (ThreadStartStruct->gcontDialogCondition, mutex);
651         g_mutex_unlock (mutex);
652         g_mutex_free (mutex);
653         mutex = NULL;
654         g_cond_free (ThreadStartStruct->gcontDialogCondition);
655         ThreadStartStruct->gcontEachCondition = NULL;
656     }
657 	/*
658     if (glistEachThreads){
659         g_list_free (glistEachThreads);
660     }*/
661     if (Error){
662         g_error_free(Error);
663         Error = NULL;
664     }
665     CallUserCommand_StartThreadStructure_freeStruct ( &ThreadStartStruct);
666     TRACEIT(10,"CallUserCommand_MainEntryThread			end");
667     g_thread_exit(0);
668 }
669 
670 
CallUserCommand_ParseCommand(struct _CallUserCommand_StartThreadStructure * ThreadStartStruct)671 int CallUserCommand_ParseCommand(struct _CallUserCommand_StartThreadStructure *ThreadStartStruct){
672     TRACEIT (10, "CallUserCommand_ParseCommand      start");
673     //this function is used to parse the command and fill the workingdir in ThreadStartStruct
674     //it will return 0 even the user aports the operation (look into ThreadStartStruct)
675     //returns -1 if an error occurs
676     if (ThreadStartStruct == NULL || ThreadStartStruct->OurUserDataListItem==NULL || ThreadStartStruct->OurUserDataListItem->ListElement==NULL){
677         TRACEIT (2, "CallUSerCommand_CallToSystem           Parameter NULL");
678         return -1;
679     }
680 
681     int         iRet = 0;
682     GList       *glistBuf = NULL;
683     int         iCallType;
684     struct _UserCommandList *UserCommandStruct = ((struct _UserCommandList *)ThreadStartStruct->OurUserDataListItem->ListElement);
685 
686 
687     if (ThreadStartStruct->gstrWorkingDir != NULL){
688         g_string_free(ThreadStartStruct->gstrWorkingDir, TRUE);
689         ThreadStartStruct->gstrWorkingDir = NULL;
690     }
691     if (ThreadStartStruct->gstrParsedCommand != NULL){
692         g_string_free(ThreadStartStruct->gstrParsedCommand, TRUE);
693         ThreadStartStruct->gstrParsedCommand = NULL;
694     }
695     if (ThreadStartStruct->gstrQuitReplyText != NULL){
696         g_string_free(ThreadStartStruct->gstrQuitReplyText, TRUE);
697         ThreadStartStruct->gstrQuitReplyText = NULL;
698     }
699     if (ThreadStartStruct->gstrActionNoteText != NULL){
700         g_string_free(ThreadStartStruct->gstrActionNoteText, TRUE);
701         ThreadStartStruct->gstrActionNoteText = NULL;
702     }
703 
704     iCallType = UserCommandStruct->option_iCallType;
705 
706     //first, let us collect some Information:
707     //the string which is copied to gstrWorking path depends on the calltype we are (all, each, list)
708     //because we allways make use of the glist which is stored with pathes we are independent from the sourcetype (SideObject, Fileshelf)
709     if (ThreadStartStruct->glistItemsWithPath!=NULL && ThreadStartStruct->glistItemsWithoutPath != NULL){
710         if (iCallType == USERCOMMAND_CALLTYPE_EACH){
711             //get the path stored with the item we currently used for the process
712             glistBuf = g_list_nth (ThreadStartStruct->glistItemsWithPath, ThreadStartStruct->uiCurrentPositionInList);
713             if (glistBuf == NULL){
714                 TRACEIT (2,"CallUserCommand_CallToSystem        internal error, item adressed not found");
715                 iRet = -1;
716             }
717             else {
718                 ThreadStartStruct->gstrWorkingDir = g_string_new( ((GString *)glistBuf->data)->str);
719             }
720         }
721         else if (iCallType == USERCOMMAND_CALLTYPE_LIST){
722             //get the path stored with the tem currently in the list
723             glistBuf = g_list_nth (ThreadStartStruct->glistItemsWithPath, ThreadStartStruct->uiCurrentPositionInList);
724             if (glistBuf == NULL){
725                 TRACEIT (2,"CallUserCommand_CallToSystem        internal error, item adressed not found");
726                 iRet = -1;
727             }
728             else{
729                 ThreadStartStruct->gstrWorkingDir = g_string_new( ((GString *)glistBuf->data)->str);
730             }
731         }
732         else{ // (iCallType == USERCOMMAND_CALLTYPE_ALL){
733             //get the path stored with the first item
734             ThreadStartStruct->gstrWorkingDir = g_string_new( ((GString *)ThreadStartStruct->glistItemsWithPath->data)->str);
735         }
736         GetPathFromPathWithName(ThreadStartStruct->gstrWorkingDir, 0);
737     }
738     else if (UserCommandStruct->gstrWorkingDir){
739         ThreadStartStruct->gstrWorkingDir = g_string_new (UserCommandStruct->gstrWorkingDir->str);
740         //printf("CallUserCommand_CallToSystem: setting Listelement\n");
741     }
742     else{
743         //printf("CallUserCommand_CallToSystem: setting homedir\n");
744         ThreadStartStruct->gstrWorkingDir = g_string_sized_new (20);
745         getHomeDirectory (ThreadStartStruct->gstrWorkingDir);
746     }
747 
748     if (iRet == 0){
749         //this function will fill the QuitReplyText and ActionNoteText too
750         iRet = ParseXMLUserCommand (ThreadStartStruct, &(ThreadStartStruct->gstrParsedCommand), &(ThreadStartStruct->gstrQuitReplyText), &(ThreadStartStruct->gstrActionNoteText), ThreadStartStruct->gstrWorkingDir);
751     }
752 
753     if (ThreadStartStruct->commStru){
754         if (iRet == 1 ){//1 == user canceled this item, 2 == user canceled all items
755             if (ThreadStartStruct->commStru->currentItem->ErrorMessage){
756                 g_string_assign (ThreadStartStruct->commStru->currentItem->ErrorMessage, "user canceled");
757             }
758             else{
759                 ThreadStartStruct->commStru->currentItem->ErrorMessage = g_string_new("user canceled");
760             }
761         }
762         else if (iRet == 2){
763             if (ThreadStartStruct->commStru->currentItem->ErrorMessage){
764                 g_string_assign (ThreadStartStruct->commStru->currentItem->ErrorMessage, "user canceled all");
765             }
766             else{
767                 ThreadStartStruct->commStru->currentItem->ErrorMessage = g_string_new("user canceled all");
768             }
769         }
770     }
771 
772     TRACEIT (10, "CallUserCommand_ParseCommand      end");
773     return iRet;
774 }
775 
776 
CallUserCommand_CallToSystem(void * data)777 int CallUserCommand_CallToSystem (void *data){
778     //this is our new function which calls the command to the system
779     //it also will parse the command
780     //commStru can be NULL, in this case we do not come from a list-call, but however, this info is also stored in ThreadStartStruct!
781     //if we come from a list-call, list->Errors will set on errors
782     struct _CallUserCommand_StartThreadStructure *ThreadStartStruct = (struct _CallUserCommand_StartThreadStructure *)data;
783     //return: 0=ok
784     //return: -1, error
785     //1 = internal error, item adressed not found
786     if (ThreadStartStruct == NULL){
787         TRACEIT (2, "CallUSerCommand_CallToSystem           Parameter NULL");
788         return -1;
789     }
790 
791     //create a little widget, displaying the command currently processing
792     int iRet=0;
793     int iNotify=0;
794     GtkWidget   *scrollwidget;
795     GtkWidget   *ActionNoteWindow=NULL;
796     GtkVBox     *VBox;
797     GtkWidget   *label=NULL;
798     struct ListWidgetCommunicationStruct *commStru = ThreadStartStruct->commStru;
799 
800     if (iRet == 0 && ThreadStartStruct->gstrActionNoteText){
801         myWrap_gdk_threads_enter("callItemsToSystem 1");
802         if (strlen (ThreadStartStruct->gstrActionNoteText->str) > 0){
803             ActionNoteWindow = CreateMyWindow(ThreadStartStruct->gstrActionNoteText->str, NULL, 400,100, TRUE, FALSE, FALSE, &iNotify, FALSE, TRUE);
804         }
805         else{
806             ActionNoteWindow = CreateMyWindow("running process", NULL, 400,100, TRUE, FALSE, FALSE, &iNotify, FALSE, TRUE);
807         }
808         AddMyIconsToWindow((GtkWindow *)ActionNoteWindow);
809         label = gtk_label_new(NULL);
810         gtk_label_set_selectable ( (GtkLabel *)label, TRUE);
811         gtk_label_set_line_wrap ( (GtkLabel *)label, TRUE);
812 
813         VBox = g_object_new(GTK_TYPE_VBOX, "spacing", 5, "homogeneous", FALSE, NULL);
814 
815         scrollwidget = gtk_scrolled_window_new(NULL,NULL);
816         gtk_scrolled_window_add_with_viewport ( (GtkScrolledWindow *)scrollwidget, label);
817         gtk_container_add(GTK_CONTAINER(VBox),scrollwidget);
818 
819         //gtk_box_pack_start(GTK_BOX(VBox),label,FALSE,FALSE,1);
820         gtk_container_add((GtkContainer *)ActionNoteWindow,(GtkWidget *)VBox);
821         gtk_widget_show_all (ActionNoteWindow);
822         myWrap_gdk_threads_leave("callItemsToSystem 1");
823     }
824 
825     //COMMAND TO SYSTEM SHELL
826     int         i_countCommand=0;
827     int         i_exitstatus=0;
828     gchar       *errors=NULL;
829     int         int_error=0;
830     GString     *gstrToken = g_string_sized_new(10);
831     GString     *gstrErrorBuf = g_string_sized_new(10);
832     GString     *gstrBuf = g_string_sized_new(10);
833 
834     GString *gstrParsedCommand = NULL;
835     GString *gstrActionNoteText = NULL;
836     GString *gstrWorkingDir = NULL;
837     GString *gstrQuitReplyText = NULL;
838     GString *gstrHomeDir = NULL;
839 
840     if (ThreadStartStruct->gstrParsedCommand){
841         gstrParsedCommand = g_string_new (ThreadStartStruct->gstrParsedCommand->str);
842     }
843     if (ThreadStartStruct->gstrActionNoteText){
844         gstrActionNoteText = g_string_new (ThreadStartStruct->gstrActionNoteText->str);
845     }
846     if (ThreadStartStruct->gstrQuitReplyText){
847         gstrQuitReplyText = g_string_new (ThreadStartStruct->gstrQuitReplyText->str);
848     }
849     if (ThreadStartStruct->gstrWorkingDir){
850         gstrWorkingDir = g_string_new (ThreadStartStruct->gstrWorkingDir->str);
851     }
852     if (ThreadStartStruct->gstrHomeDir){
853         gstrHomeDir = g_string_new (ThreadStartStruct->gstrHomeDir->str);
854     }
855 
856 
857 	//tell the waiting thread that we finished copying the information we need and we do not longer need the ThreadStartStruct
858     if (ThreadStartStruct->gcontEachCondition)
859         g_cond_signal (ThreadStartStruct->gcontEachCondition);
860 
861 	while (iRet == 0 && myTokenFunction (gstrParsedCommand, i_countCommand, "&&", gstrToken) == 1){
862         if (gstrActionNoteText){
863             TRACEIT(10,"callItemsToSystem		ActionNote is defined");
864             myWrap_gdk_threads_enter("callItemsToSystem 2");
865             if (0 != iNotify)
866                 gtk_label_set_text ((GtkLabel *)label, gstrToken->str);
867             myWrap_gdk_threads_leave("callItemsToSystem 2");
868         }
869         TRACEIT(10,"callItemsToSystem		going to call command to the system");
870         chdir(gstrWorkingDir->str);
871 
872 		if (!myWrapOf__g_spawn_command_line_sync (gstrToken->str, NULL, &errors, &i_exitstatus, NULL,TRUE)){
873 		    g_string_prepend(gstrToken, "\tCommand not found:\t\n\n");
874 		    g_string_append(gstrToken, "\n");
875 		    myWrap_gdk_threads_enter("callItemsToSystem 3");
876             MyMessageWidget(win, "Invalid command", gstrToken->str);
877             myWrap_gdk_threads_leave("callItemsToSystem 3");
878             iRet = -1;
879             break;
880 		}
881 		TRACEIT(10,"callItemsToSystem		Checking for errors....");
882         if (i_exitstatus != 0 && errors!=NULL && strlen(errors)>1){
883             g_string_assign (gstrErrorBuf, errors);
884             if (strlen(gstrErrorBuf->str) > MAXCHARSOFERROROFUSERCOMMAND){
885                 cleverCutStringToNChars(gstrErrorBuf, "\n..._SOME_TEXT_WAS_DELETED_HERE_...\n",MAXCHARSOFERROROFUSERCOMMAND);
886             }
887             if (commStru){  //write error to lists GString
888                 TRACEIT(10,"callItemsToSystem		Write error to lists GString");
889                 if (commStru->currentItem->ErrorMessage == NULL)
890                     commStru->currentItem->ErrorMessage = g_string_new(gstrErrorBuf->str);
891                 else {
892                     g_string_assign (commStru->currentItem->ErrorMessage, gstrErrorBuf->str);
893                 }
894                 int_error=1;
895             }
896             else{   //open a message widget to show the error
897                 TRACEIT(10,"callItemsToSystem		creating error widget");
898                 g_string_sprintf(gstrBuf,"Command #%d returned with error.\nEvery following process is cancelled.\nError:\n%s",i_countCommand,gstrErrorBuf->str);
899                 myWrap_gdk_threads_enter("callItemsToSystem 4");
900                 MyMessageWidget(win, "Command quits with error",gstrBuf->str);
901                 myWrap_gdk_threads_leave("callItemsToSystem 4");
902                 int_error=1;
903             }
904             TRACEIT(10,"callItemsToSystem		break after error");
905             iRet = -1;
906             break;
907         }
908 
909 		if (errors){
910             g_free(errors);
911             errors = NULL;
912 		}
913         i_countCommand++;
914 	}
915 
916 	//destroy ActionNoteWindow
917 	if (ActionNoteWindow && 0 != iNotify){
918 	    TRACEIT(10,"callItemsToSystem		ActionNoteWindow is going to be destroyed");
919 	    myWrap_gdk_threads_enter("callItemsToSystem 5");
920 	    gtk_widget_destroy(ActionNoteWindow);
921 	    myWrap_gdk_threads_leave("callItemsToSystem 5");
922     }
923 
924     TRACEIT(10,"callItemsToSystem		QuitReplayText?");
925 	if (gstrQuitReplyText && int_error == 0){
926 		myWrap_gdk_threads_enter("callItemsToSystem 6");
927 		MyMessageWidget(win, "Process end", gstrQuitReplyText->str);
928 		myWrap_gdk_threads_leave("callItemsToSystem 6");
929 
930 	}
931 	//getHomeDirectory(&homedir);
932 	chdir(gstrHomeDir->str); //thsi causes an error ! replace it by the homedirctisy stored in ThreadList (function parameter 1)
933 
934     // list->Errors
935     if (gstrBuf){
936         g_string_free(gstrBuf, TRUE);
937     }
938     if (gstrErrorBuf){
939         g_string_free(gstrErrorBuf, TRUE);
940     }
941     if (gstrToken){
942         g_string_free (gstrToken, TRUE);
943     }
944 
945     if (gstrParsedCommand){
946         g_string_free (gstrParsedCommand, TRUE);
947     }
948     if (gstrActionNoteText){
949         g_string_free (gstrActionNoteText, TRUE);
950     }
951     if (gstrQuitReplyText){
952         g_string_free (gstrQuitReplyText, TRUE);
953     }
954     if (gstrWorkingDir){
955         g_string_free (gstrWorkingDir, TRUE);
956     }
957     if (gstrHomeDir){
958         g_string_free (gstrHomeDir, TRUE);
959     }
960 
961     if (iRet  == 0){
962         iRet = int_error;
963     }
964     return iRet;
965 }
966 
967 
CallUserCommand_ProcessViaList(struct _CallUserCommand_StartThreadStructure * ThreadStartStruct)968 int CallUserCommand_ProcessViaList(struct _CallUserCommand_StartThreadStructure *ThreadStartStruct){
969     //data is from type struct _CallUserCommand_StartThreadStructur
970     //this function processes userdata via list
971     //we use our listwidget which we have developed over several versions
972     //so we have to create the right list filled with the listitems
973 	TRACEIT(10,"CallUserCommand_ProcessViaList		start");
974 	if (ThreadStartStruct == NULL){
975 		TRACEIT(10,"CallUserCommand_ProcessViaList		ends");
976 		//g_thread_exit(0);
977 		return -1;
978 	}
979 
980 	//we will need this list, but we have to create it in here!
981 	struct CopyReMoveList   *list = NULL;
982 	struct CopyReMoveList   *listbuf = NULL;
983 	int     i=0;
984 	//char    buf[320];
985 	GList   *glistBuf=NULL;
986 	//int iRet = 0;
987 	//int iItemsCount=0;
988 	struct _UserCommandList *UserCommandList = (struct _UserCommandList *) (ThreadStartStruct->OurUserDataListItem->ListElement);
989 
990 
991 	struct ListWidgetCommunicationStruct *commStru = malloc(sizeof(struct ListWidgetCommunicationStruct));
992 	if (commStru == NULL){
993         TRACEIT (2, "CAllUserCommand_ProcessViaList     error allocating memory");
994         return -1;
995 	}
996 	//First, lets create the list widget where we view the items
997 	GtkWidget               *Window;
998 	GtkWidget               *scrollWindow;
999 	GtkWidget               *listView;
1000 	GtkListStore            *listStore;
1001 	GtkTreeIter             iter;
1002 	GtkTreeViewColumn   	*col_Items;
1003 	GtkTreeViewColumn       *col_ItemNumbers;
1004 	GtkTreeViewColumn       *col_Errors;
1005 	GtkCellRenderer     	*renderer;
1006 	GtkCellRenderer         *renderer2;
1007 	GtkButton               *CancelButton;
1008 	GtkButton               *CloseButton;
1009 	GtkButton               *continueButton;
1010 	GtkButton               *pauseButton;
1011 	GtkWidget               *TheLabel;
1012 	GtkVBox                 *VBox;
1013 	GtkWidget               *ButtonBox;
1014 	GString                 *WindowName = g_string_new(MYNAMESHORT);    //freed when the commStru gets freed
1015 
1016 	myWrap_gdk_threads_enter("CallUserCommand_ProcessViaList 1");
1017 
1018 	if (UserCommandList->option_gstrCaption){
1019         g_string_assign (WindowName, UserCommandList->option_gstrCaption->str);
1020 	}
1021 
1022 	Window = CreateMyWindow(WindowName->str, NULL, 400,200,TRUE, FALSE, TRUE, NULL, FALSE, FALSE);
1023 	if (Window == NULL){
1024         g_string_free(WindowName, TRUE);
1025         free(commStru);
1026         TRACEIT(1,"CallUserCommand_ProcessViaList		end, window could not be created");
1027         return -1;
1028 	}
1029 
1030     ThreadStartStruct->commStru = commStru;
1031     //Lets build the list (CopyReMoveList) needed to process the items with our widet
1032     //which list (with or without path) we use, we decide on the fact from which source we come
1033     if (ThreadStartStruct->OurUserDataListItem->iSourceType==SOURCE_SIDEOBJECT){
1034         glistBuf = g_list_first(ThreadStartStruct->glistItemsWithoutPath);
1035 
1036     }
1037     else if (ThreadStartStruct->OurUserDataListItem->iSourceType==SOURCE_FILESHELF){
1038         glistBuf = g_list_first(ThreadStartStruct->glistItemsWithPath);
1039     }
1040     while (glistBuf){
1041         CopyReMoveList_AddItem(&list, ((GString *)(glistBuf->data))->str, NULL, NULL, NULL, NULL);
1042         glistBuf = glistBuf->next;
1043     }
1044 
1045     //continue creating the list widget
1046 	AddMyIconsToWindow((GtkWindow *)Window);
1047 
1048 	scrollWindow = gtk_scrolled_window_new (NULL,NULL);
1049 	listView = gtk_tree_view_new ();
1050 	listStore = gtk_list_store_new( 3 , G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING  );
1051 
1052     col_Items=gtk_tree_view_column_new();
1053 	col_ItemNumbers=gtk_tree_view_column_new();
1054 	col_Errors=gtk_tree_view_column_new();
1055 	gtk_tree_view_column_set_resizable(col_Items,TRUE);
1056 	gtk_tree_view_column_set_resizable(col_ItemNumbers,TRUE);
1057 	gtk_tree_view_column_set_resizable(col_Errors,TRUE);
1058 
1059 	gtk_tree_view_column_set_title(col_ItemNumbers, "#");
1060 	gtk_tree_view_append_column(GTK_TREE_VIEW(listView),col_ItemNumbers);
1061 	renderer2 = gtk_cell_renderer_text_new();
1062 	gtk_tree_view_column_pack_start(col_ItemNumbers, renderer2, TRUE);
1063 	gtk_tree_view_column_add_attribute(col_ItemNumbers,renderer2,"text",0);
1064 
1065 	gtk_tree_view_column_set_title(col_Items, "items to process");
1066 	gtk_tree_view_append_column(GTK_TREE_VIEW(listView),col_Items);
1067 	renderer = gtk_cell_renderer_text_new();
1068 	gtk_tree_view_column_pack_start(col_Items, renderer, TRUE);
1069 	gtk_tree_view_column_add_attribute(col_Items,renderer,"text",1);
1070 
1071 	gtk_tree_view_column_set_title(col_Errors, "errors");
1072 	gtk_tree_view_append_column(GTK_TREE_VIEW(listView),col_Errors);
1073 	renderer = gtk_cell_renderer_text_new();
1074 	gtk_tree_view_column_pack_start(col_Errors, renderer, TRUE);
1075 	gtk_tree_view_column_add_attribute(col_Errors,renderer,"text",2);
1076 
1077 	//g_signal_connect (listView,"button-press-event",G_CALLBACK(oneMouseButtonPressedInLittleWindow),NULL);
1078 	g_signal_connect (Window,"delete-event",G_CALLBACK(ListWidget_DeleteEvent),commStru);
1079     //g_signal_connect (Window, "destroy", G_CALLBACK(ListWidget_End_FreeMemory),commStru); //do not use this signal in here!
1080 
1081     //was never used, its just a reminder!
1082     //    if (ThreadStartStruct->iCancelAll != 0){
1083     //    break;
1084     //    }
1085 
1086     listbuf = list;
1087 	i=1;
1088 	while(listbuf!= NULL){
1089 		//snprintf(buf,319,"%d/%d",i,ThreadStartStruct->uiSizeOfLists);
1090 		gtk_list_store_append(listStore,&iter);
1091 		gtk_list_store_set (listStore, &iter, 1, listbuf->string1->str,-1);
1092         //listbuf->listStore=listStore;   //forget it, this is just for CalcSizeAfterCopyMove
1093 
1094         CopyReMoveList_initializeMemberTo (listbuf, listStore, iter, NULL, NULL, NULL, NULL, NULL, NULL, NULL, list->CopyMoveOrRemove, NULL );
1095 
1096 		//listbuf->iter = iter;
1097 		//listbuf->status = -1;
1098 		//listbuf->CopyMoveOrRemove = list->CopyMoveOrRemove;
1099 
1100 		i++;
1101 		listbuf = listbuf->NextItem;
1102 	}
1103 	copyReMoveWidget_updateItemCounterColumn(list);
1104 
1105 	CancelButton = (GtkButton *)gtk_button_new_with_label("cancel");
1106 	g_signal_connect (CancelButton,"clicked",G_CALLBACK(ListWidget_CancelButton),(void *)commStru);
1107 
1108 	CloseButton = (GtkButton *)gtk_button_new_with_label("close");
1109 	g_signal_connect (CloseButton,"clicked",G_CALLBACK(ListWidget_CloseButton),commStru);
1110 
1111 	continueButton = (GtkButton *)gtk_button_new_with_label("continue");
1112     g_signal_connect (continueButton, "clicked", G_CALLBACK(ListWidget_continueButton), commStru);
1113 
1114     pauseButton = (GtkButton *)gtk_button_new_with_label("pause");
1115     g_signal_connect (pauseButton, "clicked", G_CALLBACK(ListWidget_pauseButton), commStru);
1116 
1117 	gtk_tree_view_set_model (GTK_TREE_VIEW(listView), GTK_TREE_MODEL(listStore));
1118 
1119     if (UserCommandList->option_gstrLabel){
1120         TheLabel = gtk_label_new(UserCommandList->option_gstrLabel->str);
1121     }
1122     else{
1123         TheLabel = gtk_label_new(UserCommandList->gstrCommand->str);
1124     }
1125 
1126 	gtk_container_add((GtkContainer *)scrollWindow, listView);
1127 	VBox = g_object_new(GTK_TYPE_VBOX, "spacing", 5, "homogeneous", FALSE, NULL);
1128 	gtk_box_pack_start(GTK_BOX(VBox),TheLabel,FALSE,FALSE,1);
1129 	gtk_box_pack_start(GTK_BOX(VBox),GTK_WIDGET(scrollWindow),TRUE,TRUE,1);
1130 
1131     ButtonBox = gtk_hbox_new ( TRUE, 3);
1132 
1133     gtk_box_pack_start(GTK_BOX(ButtonBox),GTK_WIDGET(pauseButton),TRUE,TRUE,1);
1134     gtk_box_pack_start(GTK_BOX(ButtonBox),GTK_WIDGET(continueButton),TRUE,TRUE,1);
1135 	gtk_box_pack_start(GTK_BOX(ButtonBox),GTK_WIDGET(CancelButton),TRUE,TRUE,1);
1136     gtk_box_pack_start(GTK_BOX(ButtonBox),GTK_WIDGET(CloseButton),TRUE,TRUE,1);
1137 
1138     gtk_box_pack_start(GTK_BOX(VBox),GTK_WIDGET(ButtonBox),FALSE,FALSE,1);
1139 
1140     gtk_container_add((GtkContainer *)Window,(GtkWidget *)VBox);
1141 
1142     //The widget now is ready,
1143 
1144     //we now fill the communication struct with all the info neede
1145     commStru->mainListWidget=Window;
1146     commStru->listView=listView;
1147     commStru->cancelButton=CancelButton;
1148     commStru->closeButton=CloseButton;
1149     commStru->continueButton=continueButton;
1150     commStru->pauseButton=pauseButton;
1151     commStru->firstItem=list;
1152     commStru->currentItem=list;
1153     commStru->listStore=listStore;
1154     commStru->cancellable=NULL;//g_cancellable_new();
1155     commStru->gerror=NULL;
1156     commStru->iSomeError=0;
1157     commStru->SecondThreadRunning=0;
1158     commStru->TheLabel=TheLabel;
1159     commStru->WindowName=WindowName;
1160     commStru->iCancelled=0;  //becomes 1 if the process is cancelled
1161     commStru->iListPaused=0;
1162     commStru->iListPausedAutomatic=0;
1163     commStru->FreeMemoryAndDeleteWidgetFunction = FreeMemoryAndDeleteWidgetFunction;
1164     commStru->CancelListFunction = NULL;    // we do not need this in here
1165     commStru->iCancelDialogRuns=0;
1166     commStru->iDestroyFlag =0;
1167 
1168     commStru->bOverWriteAllExisting=-1;
1169     commStru->ui64TotalBytes=0;
1170     commStru->ui64TotalBytesProcessed=0;
1171     commStru->i64StartTotalBytesCopied=-1.0;
1172     commStru->dCopySpeed=0.0;
1173     commStru->iTotalBytesValid=0;
1174     commStru->progressBar=NULL;
1175     commStru->gthrdCopyReMoveThread_1 = NULL;
1176     commStru->gthrdCopyReMoveThread_2 = NULL;
1177     commStru->mtxContinue = g_mutex_new ();
1178     commStru->iNextThreadStarted = 1;
1179     commStru->ThreadStartStruct=NULL;
1180 
1181     //last thing to do before processing the list is to show the lsit widget
1182 	gtk_widget_show_all(Window);
1183 	gtk_widget_hide(GTK_WIDGET(CloseButton));
1184 	gtk_widget_hide(GTK_WIDGET(continueButton));
1185 
1186 	prepareWidgetForDrop ((GtkWidget *)commStru->listView, 1, DNDSignal_dragdatereceive_forCopyReMoveWidget, commStru);
1187 	g_signal_connect ((GtkWidget *)commStru->listView,"drag-motion",G_CALLBACK(CopyReSizeWidget_dragmotion_signal),commStru);
1188 	g_signal_connect ((GtkWidget *)commStru->listView,"drag-leave",G_CALLBACK(CopyReSizeWidget_dragleave_signal),commStru);
1189     g_signal_connect ((GtkWidget *)commStru->listView,"key-press-event",G_CALLBACK(CopyReSizeWidget_oneKeyPressedInView),commStru);
1190     g_signal_connect ((GtkWidget *)commStru->listView,"button-press-event",G_CALLBACK(ListWidget_MousePressEventCatcher),commStru);
1191 
1192 
1193 	myWrap_gdk_threads_leave("CallUserCommand_ProcessViaList 1");
1194 
1195     //start processing the list
1196     //here are some variables we need
1197     //GtkTreePath         *pTreePath;
1198     //GtkTreeSelection    *selection;
1199     //int                 iSomeError=0;
1200 
1201     // at this moment I dont see that we need this in here
1202     //but I do clearly. When the lsit is processed and e.g. the user opens a UserDialog for each item,
1203     //its still possible to cancel the list and after that close the listwidget while the userdialog is still
1204     //open. Now when the userdialog gets closed, a segfault is the logical consequence.
1205     //therefore we need this here!
1206     //commStru->SecondThreadRunning = 1;  //I know I know this is the firstThread.
1207 
1208     ThreadStartStruct->uiCurrentPositionInList=0;
1209     commStru->ThreadStartStruct = ThreadStartStruct;
1210 
1211     commStru->gthrdCopyReMoveThread_1 = g_thread_create((GThreadFunc)CallUserCommand_ProcessItemThread, (void *)commStru , TRUE, NULL);
1212 
1213 	TRACEIT(10,"CallUserCommand_ProcessViaList		ends");
1214     //g_thread_exit(0);
1215     return 0;
1216 }
1217 
1218 
CallUserCommand_ProcessItemThread(struct ListWidgetCommunicationStruct * commStru)1219 void CallUserCommand_ProcessItemThread (struct ListWidgetCommunicationStruct *commStru){
1220     TRACEIT(10,"CallUserCommand_ProcessItemThread		start");
1221     if (commStru == NULL){
1222         TRACEIT(2,"CallUserCommand_ProcessItemThread		PARAMETER NULL");
1223         g_thread_exit(0);
1224     }
1225 
1226     int                     iStillValid=1;
1227     int                     iBreak = 0;
1228     struct _CallUserCommand_StartThreadStructure *ThreadStartStruct = commStru->ThreadStartStruct;
1229     struct CopyReMoveList   *list = NULL;
1230     GtkTreeSelection        *selection;
1231     GtkTreePath             *pTreePath;
1232     int                     iRet = 0;
1233     //int                     iSomeError=0;
1234 
1235     //struct ListWidgetCommunicationStruct *commStru = ThreadStartStruct->commStru;
1236 
1237     if (ThreadStartStruct == NULL){
1238         TRACEIT(2,"CallUserCommand_ProcessItemThread		PARAMETER NULL 2");
1239         g_thread_exit(0);
1240     }
1241 
1242     myWrap_gdk_threads_enter("CallUserCommand_ProcessViaList 2");
1243     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(commStru->listView));
1244     myWrap_gdk_threads_leave("CallUserCommand_ProcessViaList 2");
1245 
1246     commStru->SecondThreadRunning = 1;
1247 
1248     if (NULL != commStru->gthrdCopyReMoveThread_2){
1249         //this means that this is NOT the first CopyReMove Thread, as this thread will create the second thread to continue the list
1250         if (NULL != commStru->gthrdCopyReMoveThread_1){
1251             g_thread_join (commStru->gthrdCopyReMoveThread_1);  //make sure, that only one CopyReMove Thread is running at a time and the last threads memory gets freed
1252         }
1253         commStru->gthrdCopyReMoveThread_1 = commStru->gthrdCopyReMoveThread_2;  //forget the old thread and store this thread at the 1st position;
1254         commStru->gthrdCopyReMoveThread_2 = NULL;
1255     }
1256 
1257     list = commStru->currentItem;   //for faster writing. and shorter sentences
1258     if (NULL == list){
1259         //because this function will set the next currentItem for the following thread, the currentItem can be NULL, as the list ends.
1260         //So we reached the end of the list and we only have to clear everything as usual
1261         iBreak = 2;
1262     }
1263     if (iBreak==0 && list->string1==NULL  ){
1264         list->ibreak=1;
1265         iBreak = 1;
1266     }
1267     if (iBreak==0 && (list->status == -10 || commStru->iCancelled==1)){
1268         list->ibreak=1;
1269         iBreak = 1;
1270     }
1271 
1272 
1273     //while (commStru->currentItem && commStru->iCancelled==0){
1274     if (iBreak==0 && list != NULL && commStru->iCancelled==0){
1275         myWrap_gdk_threads_enter("CallUserCommand_ProcessViaList 3");
1276 
1277         gtk_tree_selection_select_iter(selection, &(list->iter));
1278         //make the scrolling follow the marked Item
1279         pTreePath = gtk_tree_model_get_path (gtk_tree_view_get_model ((GtkTreeView *)commStru->listView),&(list->iter));
1280         gtk_tree_view_scroll_to_cell ((GtkTreeView *)commStru->listView,pTreePath,NULL,TRUE,0.0,0.0);
1281         gtk_tree_path_free(pTreePath);
1282 
1283         myWrap_gdk_threads_leave("CallUserCommand_ProcessViaList 3");
1284 
1285         if (list->ErrorMessage){
1286             g_string_free(list->ErrorMessage,TRUE);
1287             list->ErrorMessage = NULL;
1288         }
1289         list->ErrorMessage = g_string_sized_new(10);    //make clear this pointer is valid
1290 
1291         if (commStru->gerror){
1292             g_error_free(commStru->gerror);
1293             commStru->gerror=NULL;
1294             TRACEIT(10,"CallUserCommand_ProcessViaList		error struct was not NULL, checkpoint 2");
1295         }
1296 
1297         //TODO check status before set/start ?
1298         list->status = 0;
1299 
1300         iRet = CallUserCommand_ParseCommand (ThreadStartStruct);
1301         if (iRet == 0 && ThreadStartStruct->iCancelAll == 0){
1302             iRet = CallUserCommand_CallToSystem (ThreadStartStruct);
1303         }
1304 
1305         list->status = 1;
1306 
1307         //if (commStru->iCancelled==1){
1308             //list->ibreak=1;
1309         //    break;
1310         //}
1311         if (ThreadStartStruct->iCancelAll == 1 || iRet == 2){
1312             commStru->iCancelled=1;
1313         }
1314 
1315         if (iRet != 0){
1316             myWrap_gdk_threads_enter("CallUserCommand_ProcessViaList 4");
1317             gtk_list_store_set (commStru->listStore, &(list->iter), 2, list->ErrorMessage->str,-1);
1318             myWrap_gdk_threads_leave("CallUserCommand_ProcessViaList 5");
1319             g_string_free (list->ErrorMessage, TRUE);
1320             list->ErrorMessage = NULL;
1321             commStru->iSomeError=1;
1322         }
1323 
1324         //ThreadStartStruct->uiCurrentPositionInList++;
1325         //commStru->currentItem = commStru->currentItem->NextItem;
1326     }
1327 
1328 
1329 
1330     g_mutex_lock (commStru->mtxContinue);
1331     iStillValid = 1;
1332 
1333     ThreadStartStruct->uiCurrentPositionInList++;
1334 
1335     if (iBreak == 2){   //iBreak=2 was set if the currentItem was NULL, in this case, this thread is the last one and we have finished the list
1336         if (commStru->iCancelled==1 || commStru->iSomeError!=0){ //error or cancel, its not our turn to close the widget, but to update some things
1337 
1338             myWrap_gdk_threads_enter("CallUserCommand_ProcessViaList 4");
1339             if (commStru->iSomeError == 1){
1340                 MyMessageWidget((GtkWindow *)commStru->mainListWidget, "ERROR", "There was at least one Error \nwhile processing the list.\nLook at the column errors and scroll up\ntill you find the error message.");
1341                 g_string_append(commStru->WindowName," ERROR");
1342             }
1343             else if (commStru->iCancelled == 1){
1344                 g_string_append(commStru->WindowName," Cancelled");
1345             }
1346             gtk_window_set_title((GtkWindow *)commStru->mainListWidget,commStru->WindowName->str);
1347 
1348             gtk_widget_show(GTK_WIDGET(commStru->closeButton));
1349             gtk_widget_hide(GTK_WIDGET(commStru->cancelButton));
1350 
1351             gtk_widget_queue_draw ((GtkWidget *)commStru->mainListWidget);
1352             myWrap_gdk_threads_leave("CallUserCommand_ProcessViaList 4");
1353 
1354             commStru->SecondThreadRunning = 0;
1355         }
1356         else if (commStru->iCancelDialogRuns==0){
1357             g_mutex_unlock (commStru->mtxContinue);
1358             iStillValid = 0;
1359             myWrap_gdk_threads_enter("CallUserCommand_ProcessViaList 5");
1360             commStru->SecondThreadRunning = 0;
1361             (commStru->FreeMemoryAndDeleteWidgetFunction)( commStru);  //here Notify MUST BE 2 other wise this call will lead to a deadlock becuase of SecondThreadRunning
1362             myWrap_gdk_threads_leave("CallUserCommand_ProcessViaList 5");
1363         }
1364         else{ //the cancel dialog is open
1365             commStru->SecondThreadRunning = 0;
1366             commStru->iDestroyFlag = 1;
1367         }
1368 
1369         if (ThreadStartStruct->gcontDialogCondition)
1370             g_cond_signal (ThreadStartStruct->gcontDialogCondition);
1371 
1372     }
1373     else if (0 == commStru->iListPaused){
1374         //we will start the next thread, in the case that the next item is NULL, the thread is created without the option to join it:
1375         commStru->iNextThreadStarted = 1;
1376 
1377         commStru->currentItem = commStru->currentItem->NextItem;
1378 
1379         if (NULL != commStru->currentItem){
1380             commStru->gthrdCopyReMoveThread_2 = g_thread_create((GThreadFunc)CallUserCommand_ProcessItemThread, (void *)commStru , TRUE, NULL);
1381         }
1382         else {
1383             g_thread_create((GThreadFunc)CallUserCommand_ProcessItemThread, (void *)commStru , FALSE, NULL);
1384         }
1385     }
1386     else{
1387         commStru->iNextThreadStarted = 0;
1388     }
1389 
1390 
1391     if (1 == iStillValid){
1392         commStru->SecondThreadRunning = 0;
1393         g_mutex_unlock (commStru->mtxContinue);
1394     }
1395 
1396 
1397     TRACEIT(10,"CallUserCommand_ProcessItemThread		ends");
1398     g_thread_exit(0);
1399 }
1400 
1401 
1402 
UserOption_callTerminal(void * Object,int iSource)1403 int UserOption_callTerminal(void *Object, int iSource){
1404     TRACEIT (10, "UserOption_callTerminal           start");
1405 
1406     if (Object == NULL){
1407         TRACEIT (2, "UserOption_callTerminal        parameter NULL");
1408         return -1;
1409 	}
1410     int iRet = UserOption_callOption (Object, iSource, TERMINALKEY);
1411 
1412     TRACEIT (10, "UserOption_callTerminal           end");
1413     return iRet;
1414 }
1415 
1416 
UserOption_callStandardEditor(void * Object,int iSource)1417 int UserOption_callStandardEditor(void *Object, int iSource){
1418     TRACEIT (10, "UserOption_callStandardEditor           start");
1419 
1420     if (Object == NULL){
1421         TRACEIT (2, "UserOption_callStandardEditor        parameter NULL");
1422         return -1;
1423 	}
1424     int iRet = UserOption_callOption (Object, iSource, STANDARDEDITORKEY);
1425 
1426     TRACEIT (10, "UserOption_callStandardEditor           end");
1427     return iRet;
1428 }
1429 
1430 
UserOption_callOption(void * Object,int iSource,const char * ccpOptioniD)1431 int UserOption_callOption (void *Object, int iSource, const char *ccpOptioniD){
1432     TRACEIT (10, "UserOption_callOption           start");
1433     if (Object == NULL || ccpOptioniD==NULL){
1434         TRACEIT (2, "UserOption_callOption        parameter NULL");
1435         return -1;
1436 	}
1437     //first load the file if necessary
1438     configFileHandling_loadConfigFile ( FALSE, FALSE );
1439 
1440     const char *ccpCommand = OptionsList_getValueByID (g_OptionsList, ccpOptioniD);
1441 
1442     if (ccpCommand == NULL){
1443         TRACEIT (6, "UserOption_callOption            no terminal key defined");
1444         return -1;
1445     }
1446 
1447     struct UserDataList *theDummyItem = malloc (sizeof (struct UserDataList));
1448     if (theDummyItem == NULL){
1449         TRACEIT (3, "UserOption_callOption            unable to allocate memory");
1450         return -1;
1451     }
1452 
1453     UserDataList_CreateDummyCommand (theDummyItem, ccpCommand, Object, iSource, USERCOMMAND_CALLTYPE_ALL );
1454     startItemsWithUserCommand(NULL, theDummyItem);
1455     UserCommandList_freeList( (struct _UserCommandList **)&((theDummyItem->ListElement)) );
1456     UserDataList_DeleteList(&theDummyItem);
1457     TRACEIT (10, "UserOption_callOption           end");
1458     return 0;
1459 }
1460 
1461 
UserDataListFromBookmarkList(struct UserDataList ** UserDataListToFill)1462 int UserDataListFromBookmarkList(struct UserDataList **UserDataListToFill){
1463     //creates a UserDataList from g_BookMarkList
1464     //will delete USerDataListToFill first if it != NULL
1465     TRACEIT (10, "UserDataListFromBookmarkList          start");
1466     if (UserDataListToFill == NULL){
1467         TRACEIT(2, "UserDataListFromBookmarkList            parameter NULL");
1468         return -1;
1469     }
1470     if (*UserDataListToFill != NULL){
1471         UserDataList_DeleteList (UserDataListToFill);
1472     }
1473 
1474     configFileHandling_loadConfigFile ( FALSE, FALSE );
1475 
1476     struct _OptionsList *BookMarkListBuf = OptionsList_getFirstItem(g_BookMarkList);
1477     if (BookMarkListBuf == NULL){
1478         TRACEIT (2, "UserDataListFromBookmarkList       no bookmarks in file? Could not get g_BookMarkList");
1479         return -1;
1480     }
1481 
1482     while (BookMarkListBuf){
1483         UserDataList_AddItem(UserDataListToFill, BookMarkListBuf->gstrName->str, (void *)BookMarkListBuf);
1484         BookMarkListBuf = BookMarkListBuf->nextItem;
1485     }
1486 
1487     TRACEIT (10, "UserDataListFromBookmarkList          end");
1488     return 0;
1489 }
1490 
1491