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