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 <stdio.h>
21 #include <stdlib.h>	//for system();
22 #include <gtk/gtk.h>
23 #ifndef NO_GIO
24 #include <gio/gio.h>
25 #endif
26 #include <sys/types.h>  //Diese hier auch f�r die Verzeichnisfunktionen und Attribute / and fork()
27 #include <sys/stat.h>	//Diese hier auch f�r die Verzeichnisfunktionen und Attribute
28 #include <dirent.h>	//Verzeichnis Zeiger und DIR - Struktur
29 #include <string.h>
30 #include <time.h>
31 #include <unistd.h> 	//e.g. chdir, usleep
32 #include <errno.h>
33 #include <glib.h>
34 
35 #include "Lists.h"
36 #include "listitems.h"
37 #include "mytrace.h"
38 #include "helpers.h"
39 #include "globalDefinitions.h"
40 #include "userdata.h"
41 #include "myfm.h"
42 
43 #include "allInclude.h"
44 
45 extern GtkWindow 	*win;
46 
makeDirectory(char * Directory,int iShowErrorMessage,GString * gstrErrorStorage)47 int makeDirectory(char *Directory, int iShowErrorMessage, GString *gstrErrorStorage){
48     //if iShowErrorMessage == 1 then a message widget may pop up, showing some error, otherwise no message widget pops up
49     //if gstrErrorStorage is != NULL the error message is written to it.
50     //return: -1 internal error
51     //return: 0 OK
52     //return: 1 Error Message
53     TRACEIT(10,"makeDirectory		start");
54 
55     int ret=-1;
56     if (Directory == NULL){
57 		TRACEIT(2,"makeDirectory		ends, Parameter NULL");
58 		return -1;
59 	}
60     GError *Error = NULL;
61     GFile *Sourcefile = g_file_new_for_path(Directory);
62     GString *gstrText=g_string_sized_new(20);
63     if (FALSE == g_file_make_directory (Sourcefile, NULL, &Error) ){
64         if (gstrErrorStorage){
65             g_string_append(gstrErrorStorage, Error->message);
66         }
67         MyMessageWidget(win, "Error while creating Directory", Error->message);
68         g_string_printf(gstrText, "error created Directory: \"%s\":%s",Directory, Error->message);
69         textbuffer_commandHistory_addText(gstrText->str,"error");
70         ret = 1;
71     }
72     else{
73         g_string_printf(gstrText, "created Directory: %s",Directory);
74         textbuffer_commandHistory_addText(gstrText->str,NULL);
75         ret = 0;
76     }
77 
78     if (Error)
79         g_error_free(Error);
80     if (Sourcefile)
81         g_object_unref(Sourcefile);
82     if (gstrText)
83         g_string_free(gstrText, TRUE);
84     Sourcefile = NULL;
85 
86     TRACEIT(10,"makeDirectory		ends");
87 	return ret;
88 }
89 
90 #define UPDATETIMESINGLEITEM 100000
91 #define UPDATETIMETOTALBYTES 500000
92 
copyItemRecursive_Callback(goffset current_num_bytes,goffset total_num_bytes,gpointer data)93 void  copyItemRecursive_Callback (goffset current_num_bytes, goffset total_num_bytes, gpointer data){
94     TRACEIT(11,"copyItemRecursive_Callback       start");
95     if (data == NULL){
96         TRACEIT(2,"copyItemRecursive_Callback       end, userdate NULL");
97         return;
98     }
99     //we have to use list, NOT commstru->currentItem, as the currentItem is set in another thread and may
100     //not be the same as the listitem aimed by this function!!
101     struct CopyReMoveList *list = (struct CopyReMoveList *)data;
102     GString *gstrBuf=g_string_sized_new(10);
103     GString *gstrSpeed=g_string_sized_new(10);
104     GString *gstrBuf2=g_string_sized_new(10);
105     double percentage=0.0;
106     double totalPercentage=0.0;
107     double myTime;
108     int iUpdateView = 0;
109     int iUpdateViewSingleItem = 0;
110 
111     GTimeVal *startTime;
112     GTimeVal nextTime;
113 
114 
115     //when finished we come up here twice, this leads to an percentage of 200%
116     //when you dont understand how this works, please mind, that copying a directory
117     //may consist of many files, for them we have to the leading if structure.
118     //every time one item finished, we add the total amount to our list variable
119 //list->ui64pTotalBytesCopied
120 
121     //Calc Percentage of the Item and write it to the list
122     startTime = list->timepStartTimeForBytesCopiedSingleItem;
123 
124     if (list->iBytesCopied == -1){
125         list->iBytesCopied = 0;
126         g_get_current_time (startTime);
127         g_time_val_add(startTime, UPDATETIMESINGLEITEM);
128         iUpdateViewSingleItem = 1;
129     }
130 
131     if (current_num_bytes == total_num_bytes){
132         if (list->lastfinishedTotalBytes != total_num_bytes){
133             list->iBytesCopied += total_num_bytes;
134             list->lastfinishedTotalBytes = total_num_bytes;
135 
136             *(list->ui64pTotalBytesCopied) += total_num_bytes;
137         }
138         else{
139             list->lastfinishedTotalBytes = -1;
140         }
141         current_num_bytes = 0;
142         iUpdateViewSingleItem = 1;
143     }
144     if (iUpdateViewSingleItem == 0){
145         g_get_current_time (&nextTime);
146         myTime = GetTimeMine(*startTime) - GetTimeMine(nextTime);
147         if ( myTime <= 0){
148             g_get_current_time (startTime);
149             g_time_val_add(startTime, UPDATETIMESINGLEITEM);
150             iUpdateViewSingleItem = 1;
151         }
152     }
153 
154     if (iUpdateViewSingleItem == 1){
155         if (list->iBytesToCopyIsValid == 1){
156             percentage = 100*(double)(list->iBytesCopied+current_num_bytes)/(double)list->iBytesToCopy;
157             g_string_printf(gstrBuf, "%0.2f", percentage);
158         }
159         else{
160             g_string_assign(gstrBuf, "na");
161         }
162 
163         myWrap_gdk_threads_enter("copyItemRecursive_Callback 1");
164         gtk_list_store_set (list->listStore, &(list->iter), 1, gstrBuf->str,-1);
165         myWrap_gdk_threads_leave("copyItemRecursive_Callback 1");
166     }
167 
168     //TotalPercentag and bytes/Sec
169     startTime = list->timepStartTimeForBytesCopied;
170 
171     //totalPercentage = (double)(*(list->ui64pTotalBytesCopied)+current_num_bytes) / *(list->ui64TotalBytes);
172     //totalPercentage = (totalPercentage>1.0)?1.0:totalPercentage;
173     if (*(list->i64pStartTotalBytesCopied)<0){    //start messuring
174         *(list->i64pStartTotalBytesCopied) = *(list->ui64pTotalBytesCopied)+current_num_bytes;
175         g_get_current_time (startTime);
176         g_time_val_add(startTime, UPDATETIMETOTALBYTES);
177     }
178     g_get_current_time (&nextTime);
179     myTime = GetTimeMine(*startTime) - GetTimeMine(nextTime);
180     if ( myTime <= 0){
181         *(list->i64pStartTotalBytesCopied) = *(list->ui64pTotalBytesCopied)+current_num_bytes - *(list->i64pStartTotalBytesCopied);
182         myTime = 0.5 - myTime;
183         *(list->dpCopySpeed) = *(list->i64pStartTotalBytesCopied) / myTime;
184 
185         *(list->i64pStartTotalBytesCopied)=-1.0;
186         iUpdateView = 1;
187     }
188     if (*(list->iTotalBytesValid)==1){
189         BytesToHumanityString ((guint64)*(list->dpCopySpeed), gstrSpeed, 1);
190         g_string_append(gstrSpeed, "/s");
191 
192         if (totalPercentage>1.0)
193             totalPercentage = 1.0;
194         else if (totalPercentage<0.0)
195             totalPercentage = 0.0;
196     }
197     else{
198         g_string_assign(gstrBuf, "in progress ...");
199     }
200 
201 
202     if (iUpdateView == 1){
203         totalPercentage = (double)(*(list->ui64pTotalBytesCopied)+current_num_bytes) / *(list->ui64TotalBytes);
204         totalPercentage = (totalPercentage>1.0)?1.0:totalPercentage;
205 
206 
207         BytesToHumanityString ((guint64)*(list->ui64TotalBytes), gstrBuf2, 1);
208 
209         g_string_printf(gstrBuf, "total: %0.0f%%, at %s (%s)", totalPercentage*100, gstrSpeed->str, gstrBuf2->str);
210 
211         myWrap_gdk_threads_enter("copyItemRecursive_Callback 2");
212         gtk_progress_bar_set_fraction (list->progressBar, totalPercentage);
213         gtk_progress_bar_set_text(list->progressBar, gstrBuf->str);
214         myWrap_gdk_threads_leave("copyItemRecursive_Callback 2");
215     }
216 
217     g_string_free(gstrBuf, TRUE);
218     g_string_free(gstrSpeed, TRUE);
219     g_string_free(gstrBuf2, TRUE);
220     TRACEIT(11,"copyItemRecursive_Callback       end");
221     return;
222 }
223 
224 
copyReMoveItemRecursive(const char * cpSource,const char * cpDest,struct ListWidgetCommunicationStruct * commstru)225 int copyReMoveItemRecursive(const char *cpSource, const char *cpDest, struct ListWidgetCommunicationStruct *commstru){
226     //return: -1:error, 1=success, 0=copy returned false or any other error, copying failed
227     //cpDest is supposed to be a path
228     //while cpSource may be a path or filename
229     //cpDest may be NULL (for deleting)
230     TRACEIT(10,"copyReMoveItemRecursive		start");
231     if ( commstru==NULL || cpSource==NULL || (cpDest==NULL && commstru->currentItem->CopyMoveOrRemove != 3) ){
232         TRACEIT(2,"copyReMoveItemRecursive		end, Parameter NULL");
233         return -1;
234     }
235 
236 /*
237 #ifdef NO_GIO
238     int iRetErrorCode=0;    //0=error, 1=0k, -1 internal error, thsi is the value returned by this function
239     GString *gstrCommandString = g_string_sized_new(20);
240     GString *gstrSource = g_string_sized_new(20);
241     GString *gstrDest = g_string_sized_new(20);
242     gchar *error=NULL;
243     int iExitStatus;
244     if (commstru->currentItem->CopyMoveOrRemove == 1){  //copy
245         g_string_printf(gstrCommandString, "%s \"%s\" \"%s\"", g_gstrCommandCopy->str, cpSource, cpDest);
246     }
247     else if (commstru->currentItem->CopyMoveOrRemove == 2){ //move
248         g_string_printf(gstrCommandString, "%s \"%s\" \"%s\"", g_gstrCommandMove->str, cpSource, cpDest);
249     }
250     else if (commstru->currentItem->CopyMoveOrRemove == 3){ //remove
251         g_string_printf(gstrCommandString, "%s \"%s\"", g_gstrCommandRemove->str, cpSource);
252     }
253 
254     myWrapOf__g_spawn_command_line_sync (gstrCommandString->str, NULL, &error, &iExitStatus, NULL, TRUE);
255 
256     if (iExitStatus != 0){
257         if (error != NULL){
258             g_string_assign(commstru->currentItem->ErrorMessage, error);
259             g_free(error);
260             error=NULL;
261         }
262         iRetErrorCode=0;    //error
263     }
264     else{
265         iRetErrorCode=1;    //OK
266     }
267 
268     myWrap_gdk_threads_enter("copyReMoveItemRecursive 1");
269     if (commstru->currentItem->CopyMoveOrRemove == 1){  //copy
270         g_string_assign(gstrDest, cpDest);
271         updateObjectsViewingFolder(gstrDest->str, TRUE);
272     }
273     else if (commstru->currentItem->CopyMoveOrRemove == 2){ //move
274         g_string_assign(gstrSource, cpSource);
275         GetPathFromPathWithName(gstrSource, 1);
276         updateObjectsViewingFolder(gstrSource->str, TRUE);
277         g_string_assign(gstrDest, cpDest);
278         updateObjectsViewingFolder(gstrDest->str, TRUE);
279     }
280     else if (commstru->currentItem->CopyMoveOrRemove == 3){ //remove
281         g_string_assign(gstrSource, cpSource);
282         GetPathFromPathWithName(gstrSource, 1);
283         updateObjectsViewingFolder(gstrSource->str, TRUE);
284     }
285     myWrap_gdk_threads_leave("copyReMoveItemRecursive 1");
286     g_string_free(gstrCommandString, TRUE);
287     g_string_free(gstrSource, TRUE);
288     g_string_free(gstrDest, TRUE);
289     TRACEIT(10,"copyReMoveItemRecursive		end");
290     return iRetErrorCode;
291 #endif //#ifdef NO_GIO
292 */
293 #ifndef NO_GIO
294 
295     gboolean iDoWeDelete = (commstru->currentItem->CopyMoveOrRemove == 3)?TRUE:FALSE;
296     struct CopyReMoveList *currentItem = commstru->currentItem;
297 
298     GString *gstrSource=g_string_sized_new(20);
299     if (!iDoWeDelete)
300         g_string_assign(gstrSource,cpDest);
301 
302     //GString *gstrDest=g_string_new(cpSource);
303     GString *gstrDest=g_string_sized_new(20);
304     g_string_assign(gstrDest, cpSource);
305     GString *gstrNames=g_string_sized_new(10);
306     gboolean bRet=FALSE;
307 
308     GFile *Sourcefile = NULL;
309     GFile *Destfile = NULL;
310 
311     struct myLocationStruct locationStru;
312 
313     int iRetRecursivItem=0;
314     int iRetFolder=0;
315     int iRetErrorCode=0;    //0=error, 1=0k, -1 internal error, thsi is the value returned by this function
316     int iRecItemCount=0;
317     int iOverwriteRet=0;
318     gboolean bCanceled = FALSE;
319 
320     bCanceled =  g_cancellable_is_cancelled (commstru->cancellable);
321 
322     //build the complete Name of the destination:
323     //get the name of the file:
324     if (bCanceled == FALSE && currentItem->status==0){
325         if (!iDoWeDelete){
326             getLastStringInPath(gstrDest);
327             checkPathForLastChar(gstrSource);   //gstrSource is filled with cpDest
328             g_string_prepend(gstrDest,gstrSource->str); //now we have the complete destination
329         }
330         g_string_assign(gstrSource, cpSource);  //now the source is valid too.
331         //printf("comming in: Source=%s\n",gstrSource->str);
332 
333         //check existance of sourceitem, and ask for permission for overwrite
334         if (!iDoWeDelete && TRUE == g_file_test( gstrDest->str, G_FILE_TEST_EXISTS)){  //Ask for permission to overwirte existing file
335             if (commstru->bOverWriteAllExisting==-1 && currentItem->bOverWriteExisting==FALSE){
336                 myWrap_gdk_threads_enter("copyReMoveItemRecursive 2");
337                 iOverwriteRet = MyEasyInputWidget_Two ((GtkWindow *)commstru->mainListWidget, "overwrite", "There is allready an item with the\nsame name in the destination directory.\nDo you want to overwrite it?\n", NULL, NULL, NULL, "Overwrite", "Overwrite all", "No to all", "No");
338                 myWrap_gdk_threads_leave("copyReMoveItemRecursive 2");
339 				if (iOverwriteRet == 0){  //Overwrite this item
340 				    //printf("overwrite item\n");
341 					currentItem->bOverWriteExisting = TRUE;
342 				}
343 				else if (iOverwriteRet == 1){ //Overwirte all items
344 				    //printf("overwrite ALL item\n");
345                     currentItem->bOverWriteExisting = TRUE;
346                     commstru->bOverWriteAllExisting = 1;
347 				}
348 				else if (iOverwriteRet == 2){ //No to all, this means we may cancel the whole list.
349 				    //printf("NO to ALL item\n");
350 				    commstru->bOverWriteAllExisting = 0;
351 				    currentItem->status=-10;
352                     //commstru->CancelListFunction(commstru);
353 				}
354 				else if (iOverwriteRet == 3){ //No to this item, we cancel this item
355 				    //printf("No to this item\n");
356                     currentItem->status=-10;    //mark it as cancelled
357 				}
358             }
359             else if (commstru->bOverWriteAllExisting==0){//-1:not asked, 1=user said yes to all, 0=user said no to all
360                  currentItem->status=-10;    //mark it as cancelled
361             }
362         }
363 
364         if (currentItem->status == 0){     //item in process, this means this function
365             //do not follow links, event if they are pointing to a directory
366             if (TRUE == checkStringIsPath( gstrSource->str ) && FALSE == g_file_test( gstrSource->str, G_FILE_TEST_IS_SYMLINK)){ //open directory and give one item after each other recursive to this function
367                 //printf("Identified as path\n");
368                 //printf("found dir:%s\n",gstrSource->str);
369                 if (!iDoWeDelete){
370                     if (TRUE == g_file_test( gstrDest->str, G_FILE_TEST_EXISTS)){
371                         if (TRUE == checkStringIsPath( gstrDest->str )){ //check if the directory allready exists
372                             iRetFolder = 0;    //folder exists, we do not need to build it.
373                         }
374                         else{
375                             iRetFolder = -1; //it seems there is all ready a file with this name, prefents us creating the directory
376                         }
377                     }
378                     else{   //we buld the directory
379                         //printf("create Dir: %s\n",gstrDest->str);
380                         //gdk_threads_enter();
381                         //iRetFolder = makeDirectory(gstrDest->str,0,gstrNames); //create the other directory, stores error message in gstrNames
382                         //return 0=ok, 1=error , -1=internal error
383                         //myWrap_gdk_threads_leave();
384                         Sourcefile = g_file_new_for_path(gstrDest->str);
385                         if (FALSE == g_file_make_directory (Sourcefile, commstru->cancellable, &(commstru->gerror)) ){
386                             g_string_append(currentItem->ErrorMessage, commstru->gerror->message);
387                             iRetFolder = -1;
388                         }
389                         else{
390                             iRetFolder = 0;
391                         }
392                         if (Sourcefile)
393                             g_object_unref(Sourcefile);
394                         Sourcefile = NULL;
395                     }
396                 }
397                 else{
398                     iRetFolder = 0;
399                 }
400                 if (0 == iRetFolder){  //directory exists lets get in there
401                     iRetErrorCode=1;    //so far so good
402                     //printf("created Drectory:%s\n",gstrDest->str);
403                     //printf("going to open Dir:%s\n", gstrSource->str);
404                     if (0 == openLocation(gstrSource->str, &locationStru, FALSE, TRUE)){  //read directories entries and process them
405                         iRetErrorCode=1;    //so far so good
406                         iRecItemCount = 0;
407                         iRetRecursivItem = 0;
408                         while ( 1==getNextItemInLocation(&locationStru, gstrNames, FALSE, TRUE)){
409                             if (strcmp(gstrNames->str,".")!=0 && strcmp(gstrNames->str,"..")!=0){
410                                 g_string_assign(gstrSource, cpSource);
411                                 checkPathForLastChar(gstrSource);
412                                 g_string_append(gstrSource, gstrNames->str);
413 
414                                 //printf("new source is:%s\nnew dest is:%s\n",gstrSource->str, gstrDest->str);
415                                 if (currentItem->CopyMoveOrRemove == 1){    //copy
416                                     iRetRecursivItem += copyReMoveItemRecursive(gstrSource->str, gstrDest->str, commstru);
417                                 }
418                                 else if (currentItem->CopyMoveOrRemove == 2){    //move
419                                     //printf("moving %s\n",gstrSource->str);
420                                     iRetRecursivItem += copyReMoveItemRecursive(gstrSource->str, gstrDest->str, commstru);
421                                 }
422                                 else if (currentItem->CopyMoveOrRemove == 3){    //remove
423                                     //printf("deleting %s\n",gstrSource->str);
424                                     iRetRecursivItem += copyReMoveItemRecursive(gstrSource->str, NULL, commstru);
425                                 }
426                                 iRecItemCount++;
427                             }
428                         }
429                         //closeDirectory(&Directory);
430                         closeLocation(&locationStru);
431                         if (iRetRecursivItem != iRecItemCount){ //error on one item in the current Directory
432                             iRetErrorCode=0;
433                         }
434                         if (currentItem->CopyMoveOrRemove == 3 || currentItem->CopyMoveOrRemove == 2){  //delete directory when ReMoved
435                             if (iRetRecursivItem == iRecItemCount){  //Dont know this makes sence
436                                 Sourcefile = g_file_new_for_path(cpSource);
437                                 //printf("try to delete directory %s\n",cpSource);
438                                 if (commstru->gerror){
439                                     g_error_free(commstru->gerror);
440                                     commstru->gerror = NULL;
441                                 }
442                                 if (FALSE == g_file_delete (Sourcefile, commstru->cancellable, &(commstru->gerror))){
443                                     //error deleting source directory
444                                     g_string_assign ( currentItem->ErrorMessage, "Error: Failed to delete source directory code 1" );
445                                     if (commstru->gerror){
446                                         g_string_append(currentItem->ErrorMessage, " Message: ");
447                                         g_string_append(currentItem->ErrorMessage, commstru->gerror->message);
448                                     }
449                                     //printf("error deleting directory 1\n");
450                                     //printf("Message: %s\n",commstru->gerror->message);
451                                     iRetErrorCode=0;
452                                 }
453                                 else{
454                                     iRetErrorCode=1;
455                                 }
456                                 //printf("going to delete directory:%s\n",cpSource);
457                                 if (Sourcefile){
458                                     g_object_unref(Sourcefile);
459                                     Sourcefile=NULL;
460                                 }
461                             }
462                             else{   //error deleting source directory, not empty
463                                 g_string_assign ( currentItem->ErrorMessage, "Error: Failed to delete source directory code 2" );
464                                 //printf("error deleting directory 2\n");
465                                 iRetErrorCode=0;
466                             }
467                         }
468                     }
469                     else{
470                         g_string_assign ( currentItem->ErrorMessage, "Error: Failed to open source directory" );
471                         //printf("error opening source directory\n");
472                         iRetErrorCode=0;
473                         //failed to open source directory
474                     }
475                 }
476                 else if (iRetFolder == 1){
477                     //g_string_assign (currentItem->ErrorMessage, gstrNames->str);
478                     iRetErrorCode=0;
479                 }
480                 else{
481                     g_string_assign (currentItem->ErrorMessage, "Error: Failed to create destination directory");
482                     //printf("error create destination directory\n");
483                     //failed to create destination directory
484                 }
485             }
486             else{   //copy a file
487                 //printf("Identified as file\n");
488                 //prepare listitems member
489                 Sourcefile = getCorrectGFileTypeFromLocation(gstrSource->str, NULL);
490                 //Sourcefile = g_file_new_for_path(gstrSource->str);
491                 if (Sourcefile != NULL){
492                     if (!iDoWeDelete)
493                         Destfile = g_file_new_for_path(gstrDest->str);
494                     if (commstru->gerror != NULL){
495                         g_error_free (commstru->gerror);
496                         commstru->gerror = NULL;
497                         TRACEIT(5,"copyReMoveItemRecursive		ErrorStruct was not NULL, checkpoint 1");
498                     }
499                     if (currentItem->CopyMoveOrRemove == 1){    //copy
500                         bRet = g_file_copy (  Sourcefile, Destfile, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, commstru->cancellable, copyItemRecursive_Callback, (void *)currentItem, &(commstru->gerror));
501                     }
502                     else if (currentItem->CopyMoveOrRemove == 2){    //move
503                         bRet = g_file_move (  Sourcefile, Destfile, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, commstru->cancellable, copyItemRecursive_Callback, (void *)currentItem, &(commstru->gerror));
504                     }
505                     else if (currentItem->CopyMoveOrRemove == 3){    //remove
506                         bRet = g_file_delete (Sourcefile, commstru->cancellable, &(commstru->gerror));
507                     }
508 
509                     //sprintf("copied: _%s_ TO _%s_\n",gstrSource->str, gstrDest->str);
510                     if (bRet)
511                         iRetErrorCode = 1;
512                     else
513                         iRetErrorCode = 0;
514                 }
515                 else{
516                     iRetErrorCode = 0;
517                     g_string_assign (currentItem->ErrorMessage, "Error acquiring pointer for source object");
518                 }
519             }
520         }
521         else{   //list->status!=-0
522             iRetErrorCode = 0;
523             g_string_assign (currentItem->ErrorMessage, "Cancelled for overwriting");
524         }
525     }
526     //else{
527     //    printf("copyReMoveItemRecursive got some bad news for you\n");
528     //}
529 
530     if (Sourcefile)
531         g_object_unref(Sourcefile);
532     if (Destfile)
533         g_object_unref(Destfile);
534 
535     g_string_free(gstrSource, TRUE);
536     g_string_free(gstrDest, TRUE);
537     g_string_free(gstrNames, TRUE);
538 
539     TRACEIT(10,"copyReMoveItemRecursive		end");
540     return iRetErrorCode;
541 
542     #endif //#ifndef NO_GIO
543 }
544 
545 
CalcSizeForCopyDialog(struct CopyReMoveList * list)546 void CalcSizeForCopyDialog(struct CopyReMoveList *list){
547     TRACEIT(10,"CalcSizeForCopyDialog		start");
548     if (list == NULL ){
549         TRACEIT(2,"CalcSizeForCopyDialog		end, Parameter NULL");
550         g_thread_exit(0);
551     }
552     if (list->string1 == NULL){
553         TRACEIT(2,"CalcSizeForCopyDialog		end, Parameter2 NULL");
554         g_thread_exit(0);
555     }
556     list->iBytesToCopyIsValid=0;
557     list->iBytesToCopy=0;
558 
559     if (0==getDirectorySize(&(list->iBytesToCopy), list->string1, &(list->ibreak), FALSE )){
560         list->iBytesToCopyIsValid=1;
561     }
562     else{
563         list->iBytesToCopyIsValid=2;    //in CopyReMoveItemsViaList, in the case we want to move, we have to wait for
564         //the the size thread to finish. �n CopyReMoveItemsViaList we check this variable for 1 or 2 to continue
565     }
566 
567     TRACEIT(10,"CalcSizeForCopyDialog		end");
568     g_thread_exit(0);
569 }
570 
571 
CopyReMoveItemsViaList_SizeCalc(void * data)572 void CopyReMoveItemsViaList_SizeCalc (void *data){
573     TRACEIT(10,"CopyReMoveItemsViaList_SizeCalc		start");
574 	if (data == NULL){
575 		TRACEIT(2,"CopyReMoveItemsViaList_SizeCalc		ends, parameter NULL" );
576 		g_thread_exit(0);
577 	}
578 	struct ListWidgetCommunicationStruct *commStru=(struct ListWidgetCommunicationStruct *)data;
579 	struct CopyReMoveList *list = commStru->firstItem;
580 
581     commStru->ui64TotalBytes=0;
582     commStru->iTotalBytesValid=0;
583     while (list){
584         list->threadCalcSize = g_thread_create((GThreadFunc)CalcSizeForCopyDialog, list , TRUE, NULL);
585         if (list->threadCalcSize != NULL){
586         	//printf("Joining thread      at CopyReMoveItemsViaList_SizeCalc\n");
587 	        g_thread_join (list->threadCalcSize);
588 	        list->threadCalcSize = NULL;	//do not join again!
589 	        //printf("Leaving thread join at CopyReMoveItemsViaList_SizeCalc\n");
590     	    commStru->ui64TotalBytes += list->iBytesToCopy;
591     	}
592         list=list->NextItem;
593     }
594     commStru->iTotalBytesValid=1;
595 	TRACEIT(10,"CopyReMoveItemsViaList_SizeCalc		end");
596 	g_thread_exit(0);
597 }
598 
599 
CopyReMoveItemsViaList(void * data)600 void CopyReMoveItemsViaList(void *data){
601     TRACEIT(10,"CopyReMoveItemsViaList		start");
602 	if (data == NULL){
603 		TRACEIT(2,"CopyReMoveItemsViaList		ends, parameter NULL" );
604 		g_thread_exit(0);
605 	}
606 	struct ListWidgetCommunicationStruct *commStru=(struct ListWidgetCommunicationStruct *)data;
607 	struct CopyReMoveList *list = NULL;
608 	GString *gstrError = g_string_sized_new(20);
609 	GString *gstrForTextBuffer = g_string_sized_new(20);
610     GtkTreePath *pTreePath;
611     GtkTreeSelection *selection;
612     int iRet=0;
613     int iBreak=0;
614     myWrap_gdk_threads_enter("CopyReMoveItemsViaList 1");
615     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(commStru->listView));
616     myWrap_gdk_threads_leave("CopyReMoveItemsViaList 1");
617     //int iSomeError=0;
618     int iStillValid=1;
619     GThread *threadCalcSource=NULL;
620 
621     /*
622         this function will process only one item: commStru->currentItem and nor more!
623         after this function anther thread (actully the same function) is called to continue the list in commStru->currentItem.
624 
625         The threads have to be created as joinable, therefore we have to join the last thread before  continuing!
626     */
627 
628     commStru->SecondThreadRunning = 1;
629 
630     if (NULL != commStru->gthrdCopyReMoveThread_2){
631         //this means that this is NOT the first CopyReMove Thread, as this thread will create the second thread to continue the list
632         if (NULL != commStru->gthrdCopyReMoveThread_1){
633             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
634         }
635         commStru->gthrdCopyReMoveThread_1 = commStru->gthrdCopyReMoveThread_2;  //forget the old thread and store this thread at the 1st position;
636         commStru->gthrdCopyReMoveThread_2 = NULL;
637     }
638 
639 
640     list = commStru->currentItem;   //for faster writing. and shorter sentences
641     if (NULL == list){
642         //because this function will set the next currentItem for the following thread, the currentItem can be NULL, as the list ends.
643         //So we reached the end of the list and we only have to clear everything as usual
644         iBreak = 2;
645     }
646 
647 
648     if (iBreak==0 && (list->string1==NULL || ( (list->CopyMoveOrRemove == 1 || list->CopyMoveOrRemove == 2) && list->string2==NULL) )){
649         list->ibreak=1;
650         iBreak = 1;
651     }
652     if (iBreak==0 && (list->status == -10 || commStru->iCancelled==1)){
653         list->ibreak=1;
654         iBreak = 1;
655     }
656 
657 
658 
659 
660     if (iBreak==0 && NULL!=commStru->currentItem && commStru->iCancelled==0){
661 
662         //list->ibreak=0;   //done in ProcessItemsViaList, the previouse function
663         myWrap_gdk_threads_enter("CopyReMoveItemsViaList 2");
664         gtk_tree_selection_select_iter(selection, &(list->iter));
665 
666         //make the scrolling follow the marked Item
667         pTreePath = gtk_tree_model_get_path (gtk_tree_view_get_model ((GtkTreeView *)commStru->listView),&(list->iter));
668         gtk_tree_view_scroll_to_cell ((GtkTreeView *)commStru->listView,pTreePath,NULL,TRUE,0.0,0.0);
669         gtk_tree_path_free(pTreePath);
670         myWrap_gdk_threads_leave("CopyReMoveItemsViaList 2");
671 
672 
673         if (list->ErrorMessage)
674             g_string_free(list->ErrorMessage,TRUE);
675         list->ErrorMessage = g_string_sized_new(10);    //make clear this pointer is valid  //TODO FREE IT AND FILL IT WITH 0 on list creation
676 
677         if (commStru->gerror){
678             g_error_free(commStru->gerror);
679             commStru->gerror=NULL;
680             TRACEIT(10,"copyItemRecursive		error struct was not NULL, checkpoint 2");
681         }
682 
683         if (list->status == -1){
684             list->status = 0;
685 
686             //calc size //the size is calculated in a nother thread now
687             //list->iBytesToCopy = 0;
688             //list->iBytesToCopyIsValid = 0;
689             list->iBytesCopied = -1; //initialize with -1, so we now when to start messuring the time
690             if (list->CopyMoveOrRemove != 3){    //do not calculate this when deleting
691                 //threadCalcSource = g_thread_create((GThreadFunc)CalcSizeForCopyDialog, list , TRUE, NULL);
692                 threadCalcSource = list->threadCalcSize;
693             }
694             //tell the textBuffer what we are giong to do:
695             if (list->CopyMoveOrRemove == 1){
696                 g_string_printf(gstrForTextBuffer, "copying \"%s\" TO  \"%s\"",list->string1->str,list->string2->str);
697             }
698             else if (list->CopyMoveOrRemove == 2){
699                 while (list->iBytesToCopyIsValid == 0){
700                     usleep(10000);
701                 //if (list->iBytesToCopyIsValid==0 && threadCalcSource ){
702                 //     g_thread_join (threadCalcSource); //we should wait for the calcthread before moving.
703                 }
704                 g_string_printf(gstrForTextBuffer, "moving \"%s\" TO  \"%s\"",list->string1->str,list->string2->str);
705             }
706             else if (list->CopyMoveOrRemove == 3){
707                 g_string_printf(gstrForTextBuffer, "deleting \"%s\"",list->string1->str);
708                 // Set the row for percentage to some text, its better to view something than nothing, because nothing means not processed yet
709                 myWrap_gdk_threads_enter("CopyReMoveItemsViaList 3");
710                 gtk_list_store_set (commStru->listStore, &(list->iter), 1, "deleting",-1);
711                 myWrap_gdk_threads_leave("CopyReMoveItemsViaList 3");
712             }
713             myWrap_gdk_threads_enter("CopyReMoveItemsViaList 4");
714             textbuffer_commandHistory_addText(gstrForTextBuffer->str, NULL);
715             myWrap_gdk_threads_leave("CopyReMoveItemsViaList 4");
716 
717             //start copying, this call is synchron
718             iRet = copyReMoveItemRecursive(list->string1->str, (list->string2)?list->string2->str:NULL, commStru);
719 
720             if (iRet==1){   //iRet == 1 : Ok
721                 list->ibreak=0;
722                 myWrap_gdk_threads_enter("CopyReMoveItemsViaList 5");
723                 gtk_list_store_set (list->listStore, &(list->iter), 1, "100.00",-1); //when no error occured we assume that we copied 100%
724                 myWrap_gdk_threads_leave("CopyReMoveItemsViaList 5");
725                 //if (list->CopyMoveOrRemove != 3){
726                     //list->threadCalcSizeAfterProcessing = g_thread_create((GThreadFunc)CalcSizeAfterCopyMove, list , TRUE, NULL);
727                 //}
728             }
729             else{
730                 list->ibreak=1;
731             }
732         }
733 
734         if (iRet == 0 ){    //Error copying look GError for information
735             g_string_erase(gstrError,0,-1);
736             if (commStru->gerror){
737                 if (G_IO_ERROR_CANCELLED != commStru->gerror->code){
738                     g_string_printf(gstrError, "Error: code: %d, message:%s",commStru->gerror->code, commStru->gerror->message);
739                     textbuffer_commandHistory_addText(gstrError->str, "error");
740                     g_error_free(commStru->gerror);
741                     commStru->gerror=NULL;
742                     commStru->iSomeError = 1;
743                 }
744                 else
745                     commStru->iSomeError = 2; //do not show the hint that there was an error
746             }
747             else if (strlen (list->ErrorMessage->str) != 0){
748                 g_string_assign (gstrError, list->ErrorMessage->str);
749                 textbuffer_commandHistory_addText(gstrError->str, "error");
750                 commStru->iSomeError = 1;
751             }
752             else{
753                 g_string_assign(gstrError, "Unknown error");
754                 textbuffer_commandHistory_addText(gstrError->str, "error");
755                 commStru->iSomeError = 1;
756             }
757             if (strlen(gstrError->str)>0){
758                 myWrap_gdk_threads_enter("CopyReMoveItemsViaList 6");
759                 gtk_list_store_set (commStru->listStore, &(list->iter), 3, gstrError->str,-1);
760                 myWrap_gdk_threads_leave("CopyReMoveItemsViaList 6");
761                 commStru->iSomeError=1;
762             }
763         }
764         else if(iRet == -1){    //internal Error
765             g_string_assign(gstrError, "BAD INTERNAL ERROR, INFORM THE PROGRAMMER");
766             textbuffer_commandHistory_addText(gstrError->str, "error");
767             myWrap_gdk_threads_enter("CopyReMoveItemsViaList 7");
768             gtk_list_store_set (commStru->listStore, &(list->iter), 3, gstrError->str,-1);
769             myWrap_gdk_threads_leave("CopyReMoveItemsViaList 7");
770             commStru->iSomeError=1;
771         }
772         //if (commStru->iCancelled==1){
773         //    list->ibreak=1;
774         //    break;
775         //}
776         //commStru->currentItem = commStru->currentItem->NextItem;
777     }
778 
779     //list->ibreak=1; //for security reason, this cancels the size calculation thread
780     //we can come up here when there was
781     //some error, in this case we may have a cancel
782     //just a cancel
783     //we finished, no error, no cancel
784     //only in the last case we going to close the widget from here
785 
786     g_mutex_lock (commStru->mtxContinue);
787     iStillValid = 1;
788     //printf("after thread 2 loop\n");
789     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
790         //printf("last item in list\n");
791         if (commStru->iCancelled==1 || commStru->iSomeError!=0){ //error or cancel, its not our turn to close the widget, but to update some things
792             //printf("Error or cancel\n");
793             myWrap_gdk_threads_enter("CopyReMoveItemsViaList 8");
794             if (commStru->iSomeError == 1){
795                 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.");
796                 g_string_append(commStru->WindowName," ERROR");
797             }
798             else if (commStru->iCancelled == 1){
799                 g_string_append(commStru->WindowName," Cancelled");
800             }
801             gtk_window_set_title((GtkWindow *)commStru->mainListWidget,commStru->WindowName->str);
802 
803             gtk_widget_show(GTK_WIDGET(commStru->closeButton));
804             gtk_widget_hide(GTK_WIDGET(commStru->cancelButton));
805 
806             gtk_widget_queue_draw ((GtkWidget *)commStru->mainListWidget);
807             myWrap_gdk_threads_leave("CopyReMoveItemsViaList 8");
808 
809         }
810         else if (commStru->iCancelDialogRuns==0){
811             //printf("check 2\n");
812             commStru->SecondThreadRunning = 0;
813             g_mutex_unlock (commStru->mtxContinue);
814             iStillValid = 0;
815             myWrap_gdk_threads_enter("CopyReMoveItemsViaList 9");
816             (commStru->FreeMemoryAndDeleteWidgetFunction)( commStru);  //here Notify MUST BE 2 other wise this call will lead to a deadlock becuase of SecondThreadRunning
817             myWrap_gdk_threads_leave("CopyReMoveItemsViaList 9");
818         }
819         else{ //the cancel dialog is open
820             //printf("check 3\n");
821             commStru->iDestroyFlag = 1;
822         }
823 
824     }
825     else if (0 == commStru->iListPaused){
826         //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:
827         commStru->iNextThreadStarted = 1;
828 
829         commStru->currentItem = commStru->currentItem->NextItem;
830 
831         if (NULL != commStru->currentItem){
832             commStru->gthrdCopyReMoveThread_2 = g_thread_create((GThreadFunc)CopyReMoveItemsViaList, (void *)commStru , TRUE, NULL);
833         }
834         else {
835             g_thread_create((GThreadFunc)CopyReMoveItemsViaList, (void *)commStru , FALSE, NULL);
836         }
837     }
838     else{
839         commStru->iNextThreadStarted = 0;
840     }
841 
842 
843     if (1 == iStillValid){
844         commStru->SecondThreadRunning = 0;
845         g_mutex_unlock (commStru->mtxContinue);
846     }
847 
848 
849 
850     //free things
851     g_string_free(gstrError, TRUE);
852     g_string_free(gstrForTextBuffer, TRUE);
853     //commStru->SecondThreadRunning = 0; NOT HERE, because of the last else if
854 
855 	TRACEIT(10,"CopyReMoveItemsViaList		ends");
856 	g_thread_exit(0);
857 }
858 
859 
fileAttributesGet(struct FileAttributs * attribs,char * path,char * name)860 int fileAttributesGet(struct FileAttributs *attribs,char *path, char *name){
861     //DO NOT FORGETT: FREE MEMORY (GSTRING IF IT IS A LINK)
862     //example:
863     //      if (attribs->gstrLinkTarget)
864     //          g_string_free(attribs->gstrLinkTarget, TRUE);
865     //
866     //name can be NULL, in this case path is expected to be the whole name with path
867 	TRACEIT(11,"fileAttributesGet		start");
868 	int i;
869 	if (attribs == NULL || path == NULL){
870 		TRACEIT(10,"fileAttributesGet		ends");
871 		return -1;
872 	}
873 
874 	GString *gstrFullName = g_string_new(path);
875 	GString *gstrBuf = g_string_sized_new(10);
876 	GString *gstrName = g_string_sized_new(10);
877 	struct stat fileattributes;
878 
879     attribs->size = 0;
880     attribs->owner = 0;
881     attribs->group = 0;
882     sprintf(attribs->permission,"-");
883     strcat(attribs->permission,"-");
884     strcat(attribs->permission,"-");
885     strcat(attribs->permission,"-");
886     strcat(attribs->permission,"-");
887     strcat(attribs->permission,"-");
888     strcat(attribs->permission,"-");
889     strcat(attribs->permission,"-");
890     strcat(attribs->permission,"-");
891     sprintf(attribs->accessed,"na");	//keep in mind, that the accessed array is 30 bytes in size (defined in listitems.h)
892     sprintf(attribs->changed,"na");
893     attribs->gstrLinkTarget=NULL;
894 
895     if ( name!=NULL ){
896         checkPathForLastChar(gstrFullName);
897         g_string_append(gstrFullName, name);
898     }
899 
900 	if (FALSE == g_file_test(gstrFullName->str,G_FILE_TEST_EXISTS)){
901 		g_string_free(gstrFullName,TRUE);
902 		g_string_free(gstrBuf,TRUE);
903 		g_string_free(gstrName, TRUE);
904 		TRACEIT(11,"fileAttributesGet		end, File not found");
905 		return -1;
906 	}
907 
908 	if (stat(gstrFullName->str, &fileattributes) == -1){
909         sprintf(attribs->accessed,"fstab: errno=%d", errno);	//keep in mind, that the accessed array is 30 bytes in size (defined in listitems.h)
910 	}
911 	else{
912 		//size
913 		attribs->size = (guint64)fileattributes.st_size;
914 
915 		//owner
916 		attribs->owner = fileattributes.st_uid;
917 
918 		//group
919 		attribs->group = fileattributes.st_gid;
920 
921 		//permission
922 		sprintf(attribs->permission,(S_IRUSR & fileattributes.st_mode)?"r":"-");
923 		strcat(attribs->permission,(S_IWUSR & fileattributes.st_mode)?"w":"-");
924 		strcat(attribs->permission,(S_IXUSR & fileattributes.st_mode)?"x":"-");
925 		strcat(attribs->permission,(S_IRGRP & fileattributes.st_mode)?"r":"-");
926 		strcat(attribs->permission,(S_IWGRP & fileattributes.st_mode)?"w":"-");
927 		strcat(attribs->permission,(S_IXGRP & fileattributes.st_mode)?"x":"-");
928 		strcat(attribs->permission,(S_IROTH & fileattributes.st_mode)?"r":"-");
929 		strcat(attribs->permission,(S_IWOTH & fileattributes.st_mode)?"w":"-");
930 		strcat(attribs->permission,(S_IXOTH & fileattributes.st_mode)?"x":"-");
931 
932         attribs->type_d = (S_IFDIR & fileattributes.st_mode)?4:0;
933 		//accessed
934 		attribs->utaccessed=fileattributes.st_atime;
935 		sprintf(attribs->accessed,"%s",	ctime(&fileattributes.st_atime));
936 		attribs->accessed[strlen(attribs->accessed)-1]='\0';
937 
938 		//changed
939 		attribs->utchanged=fileattributes.st_mtime;
940 		sprintf(attribs->changed,"%s",	ctime(&fileattributes.st_mtime));
941 		attribs->changed[strlen(attribs->changed)-1]='\0';
942 
943 		//hiddenfile
944 		if (name == NULL){
945 		    g_string_assign(gstrBuf, gstrFullName->str);
946             getLastStringInPath(gstrBuf);
947             name = gstrBuf->str;
948 		}
949 		if (name[0] == '.' && strcmp(name,".") != 0 && strcmp(name,"..") != 0)
950 			attribs->hiddenfile = TRUE;
951 		else
952 			attribs->hiddenfile = FALSE;
953 	}
954 	//check if we have a Link and set the appropriate variables
955 #ifndef NO_GIO
956 	attribs->gstrLinkTarget=NULL;
957 	GFileInfo *SymlinkInfo=NULL;
958 	GFile *Symfile=NULL;
959 	const char *cpTarget=NULL;
960 	int iItsASymlink=0; //1 if it is a symlink, but its no garantee the links exists!!
961     if (TRUE == g_file_test( gstrFullName->str, G_FILE_TEST_IS_SYMLINK)){
962         //printf("found symlink: %s\n", gstrFullName->str);
963         iItsASymlink=1;
964         attribs->type_d = 10;
965         Symfile = g_file_new_for_path(gstrFullName->str);
966         SymlinkInfo = g_file_query_info (Symfile, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
967                                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
968                                                          NULL,
969                                                          NULL);
970         cpTarget = g_file_info_get_attribute_byte_string (SymlinkInfo,G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
971         if (cpTarget){
972             //printf("target: %s\n", cpTarget);
973             attribs->gstrLinkTarget = g_string_new(cpTarget);
974             if (g_file_test( attribs->gstrLinkTarget->str, G_FILE_TEST_EXISTS)){
975                 if (checkStringIsPath(attribs->gstrLinkTarget->str)){
976                     attribs->type_d=4; //handle as path
977                 }
978                 else{
979                     attribs->type_d=0; //handle as ordinary file
980                 }
981             }
982         }
983         else{
984            // printf("No target found\n");
985         }
986 
987         if (Symfile)
988             g_object_unref(Symfile);
989         if (SymlinkInfo)
990             g_object_unref(SymlinkInfo);
991     }
992 #endif
993 
994 	//type
995 
996 #ifndef NO_GIO
997 	if (iItsASymlink==1 && attribs->gstrLinkTarget !=NULL){
998         g_string_assign (gstrName, attribs->gstrLinkTarget->str);
999         getLastStringInPath(gstrName);
1000 	}
1001 	else{
1002         g_string_assign(gstrName, name);
1003 	}
1004 #endif //#ifndef NO_GIO
1005 #ifdef NO_GIO
1006     g_string_assign(gstrName, name);
1007 #endif //#ifdef NO_GIO
1008 	int len = strlen(gstrName->str);
1009 	int foundit=0;
1010 	for (i=1; i<=MAXTYPELENGTH; i++){
1011 		//was len-i<=1 , but then e.g. 1.jpg was not recognized
1012 		//if (len - i < 1 || dirzeiger->d_type == 4 || dirzeiger->d_type == 10){	//removed because we need this function for the fileshelf too, and do not have an directory opened
1013 		if (len - i < 1 || attribs->type_d == 4 || attribs->type_d == 10){
1014 		    if (attribs->type_d == 10)  //without this, short files will be marked with "-", and than could not be distinguished from directories. important, when marking all items of the same type
1015                 foundit = 10;
1016 			else if (attribs->type_d == 4)
1017                 foundit = 4;
1018 			break;
1019 		}
1020 		if (gstrName->str[len-i] == '.'){
1021 			foundit = 1;
1022 			strncpy (attribs->type,&(gstrName->str[len-i+1]),FIELDSIZE);
1023 			break;
1024 		}
1025 	}
1026 	if (foundit==0)
1027 		strncpy(attribs->type,"-",FIELDSIZE);   //this things are used to distinguish between types, used when marking all items of the same type
1028     else if(foundit==10)
1029         strncpy(attribs->type,"---",FIELDSIZE);
1030     else if(foundit==4)
1031         strncpy(attribs->type,"--",FIELDSIZE);
1032 
1033     g_string_free(gstrName,TRUE);
1034 	g_string_free(gstrFullName,TRUE);
1035 	g_string_free(gstrBuf,TRUE);
1036 
1037 	TRACEIT(11,"fileAttributesGet		ends");
1038 	return 0;
1039 }
1040 
1041 
openLocation(char * cpLocation,struct myLocationStruct * struLocation,gboolean bUseMessageWidgets,gboolean bMakeThreadSave)1042 int openLocation (char *cpLocation, struct myLocationStruct *struLocation, gboolean bUseMessageWidgets, gboolean bMakeThreadSave){
1043     //this is NOT THREAD SAVE if bUseMessageWidgets == TRUE
1044     //bUseMassageWidget=True: show error messages
1045     //bMakeThreadSave=True: use gdk_threads_enter/leave
1046     //return: 0: success opening directory, -1: error
1047     //the struLocation must be a pointer to a valid structure, it is not created inside here, nor it is freed!!
1048     //however the things which are going to be filled into this structure are freed in closeLocation
1049     //errors on opneing a location are shown as messageboxes from within this function,so the calling function does not have to interprete errors
1050     //EVEN ON AN ERROR YOU HAVE TO CALL closeLocation to free the structure struLocation
1051     TRACEIT(10,"openLocation		start");
1052     GString *gstrBuf = g_string_sized_new(10);
1053     if (cpLocation==NULL || struLocation==NULL){
1054         g_string_free(gstrBuf, TRUE);
1055         TRACEIT(2,"openLocation		end, Parameter NULL");
1056         return -1;
1057     }
1058 
1059     //first step is to initialize the structure (not the structure itself but its member)
1060     struLocation->gfileLocation=NULL;
1061     struLocation->error=NULL;
1062     struLocation->gstrLocation=NULL;
1063     struLocation->enumerator=NULL;
1064     struLocation->gfileInfo=NULL;
1065 
1066     int iItsPath = -1;  //-1 unknown, 0=uri, 1=path
1067     //first we have to decide if we have a path, or a uri:
1068     //when the first character is a '/' its supposed to be a path.
1069     if (strlen(cpLocation) >= 2){
1070         if (cpLocation[0]=='/')
1071             iItsPath = 1;
1072         else
1073             iItsPath = 0;
1074     }
1075     else{//its a path
1076         iItsPath = 1;
1077     }
1078 
1079     if (iItsPath == 1 && checkStringIsPath(cpLocation) == FALSE){
1080         g_string_free(gstrBuf, TRUE);
1081         TRACEIT(7,"openLocation		end, directory not found:");
1082         TRACEIT(7,cpLocation);
1083         return -1;
1084     }
1085 
1086     struLocation->gstrLocation = g_string_new(cpLocation);
1087 
1088     //Now lets create the GFile Object
1089     if (iItsPath == 0){ //uri
1090         struLocation->gfileLocation = g_file_new_for_uri (cpLocation);
1091     }
1092     else if (iItsPath == 1){ //path
1093         struLocation->gfileLocation = g_file_new_for_path (cpLocation);
1094     }
1095     else{
1096         g_string_free(gstrBuf, TRUE);
1097         if (bUseMessageWidgets){
1098             if (bMakeThreadSave)
1099                 myWrap_gdk_threads_enter("openLocation 1");
1100             MyMessageWidget(win, "Error", "The type of the location could not be recognized.\nError opening new location");
1101             if (bMakeThreadSave)
1102                 myWrap_gdk_threads_leave("openLocation 1");
1103         }
1104         TRACEIT(5,"openLocation		end, type not recognized:");
1105         TRACEIT(5,cpLocation);
1106         return -1;
1107     }
1108 
1109     struLocation->enumerator = g_file_enumerate_children (struLocation->gfileLocation, "standard::name", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &(struLocation->error));
1110     if (struLocation->error != NULL){
1111         if (bUseMessageWidgets){
1112             g_string_printf(gstrBuf, "Unable to open location:\n%s\nError:%d:%s",cpLocation, struLocation->error->code, struLocation->error->message);
1113             if (bMakeThreadSave)
1114                 myWrap_gdk_threads_enter("openLocation 2");
1115             MyMessageWidget(NULL,"Error",gstrBuf->str);
1116             if (bMakeThreadSave)
1117                 myWrap_gdk_threads_leave("openLocation 2");
1118         }
1119         g_error_free(struLocation->error);
1120         struLocation->error=NULL;
1121         g_string_free(gstrBuf, TRUE);
1122         TRACEIT(5,"openLocation		end, location not supported:");
1123         TRACEIT(5,cpLocation);
1124         return -1;
1125     }
1126 
1127     g_string_free(gstrBuf, TRUE);
1128     TRACEIT(10,"openLocation		end");
1129     return 0;   //success, directory opened
1130 }
1131 
1132 
getNextItemInLocation(struct myLocationStruct * struLocation,GString * gstrName,gboolean bUseMessageWidgets,gboolean bMakeThreadSave)1133 int getNextItemInLocation(struct myLocationStruct *struLocation, GString *gstrName, gboolean bUseMessageWidgets, gboolean bMakeThreadSave){
1134     //return: -1=error, 1=success, 0=no item left
1135     TRACEIT(10,"getNextItemInLocation		start");
1136     const char *cpName=NULL;
1137     if (struLocation==NULL || gstrName==NULL){
1138         TRACEIT(2,"getNextItemInLocation		end, parameter NULL");
1139         return -1;
1140     }
1141 
1142     if (struLocation->gfileLocation==NULL || struLocation->enumerator==NULL){
1143         g_string_erase(gstrName, 0, -1);
1144         TRACEIT(4,"getNextItemInLocation		end, struLoction not initialized properly");
1145         return -1;
1146     }
1147 
1148     if (struLocation->gfileInfo!=NULL){
1149         g_object_unref(struLocation->gfileInfo);
1150         struLocation->gfileInfo=NULL;
1151     }
1152 
1153     struLocation->gfileInfo = g_file_enumerator_next_file (struLocation->enumerator, NULL, &(struLocation->error));
1154 
1155     if (struLocation->error != NULL){
1156         if (bUseMessageWidgets){
1157             if (bMakeThreadSave)
1158                 myWrap_gdk_threads_enter("getNextItemInLocation 1");
1159             MyMessageWidget(NULL,"Error",struLocation->error->message);
1160             if (bMakeThreadSave)
1161                 myWrap_gdk_threads_enter("getNextItemInLocation 1");
1162         }
1163         g_error_free(struLocation->error);
1164         struLocation->error=NULL;
1165     }
1166 
1167     if (struLocation->gfileInfo == NULL){   //no item left at location
1168         g_string_erase(gstrName, 0, -1);
1169         TRACEIT(10,"getNextItemInLocation		end, location finished");
1170         return 0;   //no more items to come
1171     }
1172 
1173     //G_FILE_ATTRIBUTE_STANDARD_COPY_NAME , G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
1174     //cpName = g_file_info_get_attribute_as_string (struLocation->gfileInfo, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1175     cpName = g_file_info_get_name(struLocation->gfileInfo);
1176     if (cpName==NULL){
1177         //MyMessageWidget(NULL,"Error","Error retreiving name of item at location, aborting.");
1178         TRACEIT(4,"getNextItemInLocation		end, Error retreiving name of item at location");
1179     }
1180     else{
1181         g_string_assign(gstrName, cpName);
1182     }
1183 
1184     if (struLocation->gfileInfo!=NULL){
1185         g_object_unref(struLocation->gfileInfo);
1186         struLocation->gfileInfo=NULL;
1187     }
1188 
1189     TRACEIT(10,"getNextItemInLocation		end");
1190     return 1;   //more items to come
1191 }
1192 
1193 
closeLocation(struct myLocationStruct * struLocation)1194 int closeLocation (struct myLocationStruct *struLocation){
1195     //frees all the things created and stored in struLocation.
1196     //make sure you call this function even if one of the leading functions (openLocation ...) fails!
1197     //return: 0=ok, -1=internal error;
1198     TRACEIT(10,"closeLocation		start");
1199     if (struLocation == NULL){
1200         TRACEIT(2,"closeLocation		end, Parameter NULL");
1201     }
1202 
1203     if (struLocation->gstrLocation!=NULL){
1204         g_string_free(struLocation->gstrLocation, TRUE);
1205         struLocation->gstrLocation=NULL;
1206     }
1207 
1208     if (struLocation->error!=NULL){
1209         g_error_free(struLocation->error);
1210         struLocation->error=NULL;
1211     }
1212     if (struLocation->gfileInfo!=NULL){
1213         g_object_unref(struLocation->gfileInfo);
1214         struLocation->gfileInfo=NULL;
1215     }
1216 
1217     if (struLocation->enumerator!=NULL){
1218         g_file_enumerator_close (struLocation->enumerator,NULL,NULL);
1219         g_object_unref(struLocation->enumerator);
1220         struLocation->enumerator=NULL;
1221     }
1222 
1223     if (struLocation->gfileLocation!=NULL){
1224         g_object_unref(struLocation->gfileLocation);
1225         struLocation->gfileLocation=NULL;
1226     }
1227 
1228     TRACEIT(10,"closeLocation		end");
1229     return 0;
1230 }
1231 
1232 
getSizeOfSelectedItemsRecursive(struct RecursiveSizeStructure * stru)1233 static void getSizeOfSelectedItemsRecursive(struct RecursiveSizeStructure *stru){
1234 	TRACEIT(10,"getSizeOfSelectedItemsRecursive		start");
1235 
1236 	GString *gstrItem=g_string_sized_new(20);
1237 	int i;
1238 
1239 	for (i=0; i<stru->ItemCounter; i++){
1240 		if (*(stru->ibreak) != 0){
1241 			break;
1242 		}
1243 		if (stru->intPTypes[i] == 4 /*|| stru->intPTypes[i] == 10*/){
1244 			if (stru->SideObjectOrFileshelfItem==SOURCE_SIDEOBJECT){
1245 	    		g_string_assign(gstrItem, stru->gstrPath->str);
1246 				checkPathForLastChar(gstrItem);
1247     			g_string_append(gstrItem, (stru->gstrDPItems)[i]->str);
1248 			}
1249 			else{
1250 				g_string_assign(gstrItem, (stru->gstrDPItems)[i]->str);
1251 			}
1252 			if (0 != getDirectorySize(&(stru->guint64_size), gstrItem, stru->ibreak, FALSE)){  //Error opening directory
1253                 stru->ErrorOccured=1;
1254 			}
1255         }
1256     	else{
1257 			stru->guint64_size+=stru->intPSizes[i];
1258     	}
1259     	if (*(stru->ibreak) != 0){
1260     			break;
1261     	}
1262     }
1263 
1264 	//clean up
1265 	g_string_free(gstrItem,TRUE);
1266 
1267 	//We are ready for clean up the structure, tell this the other thread:
1268 	stru->iReadyForCleanUp = 1;
1269 
1270 	TRACEIT(10,"getSizeOfSelectedItemsRecursive		ends");
1271 	g_thread_exit(0);
1272 }
1273 
1274 
getSizeOfSelectedItemsRecursive_dialog(void * data)1275 void getSizeOfSelectedItemsRecursive_dialog(void *data){
1276 	TRACEIT(10,"getSizeOfSelectedItemsRecursive_dialog		start");
1277 	GtkWidget *dialog, *label;
1278 	int i;
1279 	int len;
1280 	struct RecursiveSizeStructure *stru = (struct RecursiveSizeStructure *) data;
1281 	GString *gstrBuf = g_string_sized_new(10);
1282 	GString *gstrBuf2 = g_string_sized_new(10);
1283 	char buf[320];  //just needed to hold the size (only the number), g_printf does not know how to handle 64bit numbers
1284 	GtkButton *CancelButton;
1285 	GtkVBox *VBox;
1286 	GError *error = NULL;
1287 	//GThread *thread = NULL;
1288 
1289 	myWrap_gdk_threads_enter("getSizeOfSelectedItemsRecursive_dialog 1");
1290 
1291 	stru->ibreak = malloc (sizeof(int));
1292 	*(stru->ibreak) = 0;
1293 	stru->theLabel = gtk_label_new("sdf");
1294 	stru->iReadyForCleanUp=1;
1295 	stru->guint64_size=0;
1296 	stru->ErrorOccured=0;
1297 
1298 	int iNotify=0;
1299 
1300 	//simple dialog
1301 	dialog = CreateMyWindow("Size of selected items",stru->mainWin,400,250,FALSE, TRUE, TRUE, &iNotify, FALSE, FALSE);
1302 	//dialog = CreateMyWindow("Size of selected items",NULL,400,250,FALSE, FALSE);
1303 	AddMyIconsToWindow((GtkWindow *)dialog);
1304 
1305 	CancelButton = (GtkButton *)gtk_button_new_with_label("Ok");
1306 	g_signal_connect (CancelButton,"clicked",G_CALLBACK(CancelButtonFunctionForIBreak),stru->ibreak);
1307 
1308 	VBox = g_object_new(GTK_TYPE_VBOX, "spacing", 5, "homogeneous", FALSE, NULL);
1309 
1310 	g_string_printf(gstrBuf,"\tCalculates the size of the selected items.\t\n\tDirectories are searched recursively.\t\n\n\tItems selected: %d\n",stru->ItemCounter);
1311 
1312 	label = gtk_label_new(gstrBuf->str);
1313 
1314 	gtk_box_pack_start(GTK_BOX(VBox),label,TRUE,TRUE,1);
1315 	gtk_box_pack_start(GTK_BOX(VBox),stru->theLabel,TRUE,TRUE,1);
1316 	gtk_box_pack_start(GTK_BOX(VBox),GTK_WIDGET(CancelButton),FALSE,FALSE,1);
1317 	gtk_container_add((GtkContainer *)dialog,(GtkWidget *)VBox);
1318 
1319 	gtk_widget_show_all(dialog);
1320 	myWrap_gdk_threads_leave("getSizeOfSelectedItemsRecursive_dialog 1");
1321 
1322 	if (stru->ItemStringCounter != stru->ItemCounter){	//Error allocation memory for storing ItemInformation
1323 		gtk_label_set_text ((GtkLabel *)stru->theLabel, "Sorry, an error occured while memory allocation.\nUnable to calculate size.");
1324 		*(stru->ibreak) = 1;
1325 		stru->iReadyForCleanUp = 1;
1326 	}
1327 	else{
1328 		stru->iReadyForCleanUp=0;
1329 		//thread = g_thread_create((GThreadFunc)getSizeOfSelectedItemsRecursive, (void *)stru , TRUE, &error);
1330 		g_thread_create((GThreadFunc)getSizeOfSelectedItemsRecursive, (void *)stru , FALSE, &error);
1331 		if (error != NULL){
1332             TRACEIT (3 ,"getSizeOfSelectedItemsRecursive_dialog     error creating thread:");
1333             TRACEIT (3 ,error->message);
1334             g_error_free (error);
1335             error = NULL;
1336 		}
1337 		//do not make this thread joinable and join in here, because in this case the little widget showing the size
1338 		//will not be updated anymore.
1339 		//g_thread_join (thread);
1340 	}
1341 
1342 	do{
1343         BytesToHumanityString (stru->guint64_size, gstrBuf2, 0);
1344 		snprintf(buf,99,"%lld",stru->guint64_size);
1345         g_string_assign(gstrBuf,buf);
1346 		len = strlen(gstrBuf->str)-3;
1347 		while (len>0){
1348 			g_string_insert_c(gstrBuf,len,'.');
1349 			len -=3;
1350 		}
1351 		strcpy(buf,gstrBuf->str);
1352 		if (stru->ErrorOccured == 1){
1353             g_string_sprintf(gstrBuf,"\tSelected need %s (%s bytes)\t\nBut there was at least one directory\nthat could not be opened.",gstrBuf2->str, buf);
1354 		}
1355 		else{
1356             g_string_sprintf(gstrBuf,"\tSelected need %s (%s bytes)\t",gstrBuf2->str, buf);
1357 		}
1358 		myWrap_gdk_threads_enter("getSizeOfSelectedItemsRecursive_dialog 2" );
1359 		if (iNotify==1){    //as long this is 1 the dialog is valid and was not destroyed
1360             gtk_label_set_text ((GtkLabel *)stru->theLabel, gstrBuf->str);
1361 		}
1362 		else{
1363             *(stru->ibreak)=1;
1364 		}
1365 		myWrap_gdk_threads_leave("getSizeOfSelectedItemsRecursive_dialog 2");
1366 		usleep(100000);
1367 	}while(*(stru->ibreak) == 0);
1368 
1369 	while (stru->iReadyForCleanUp != 1){
1370 		//The other thread has not finished yet, we should wait for him.
1371 		usleep(100000);
1372 	}
1373 
1374 	myWrap_gdk_threads_enter("getSizeOfSelectedItemsRecursive_dialog 3");
1375 	if (iNotify==1){    //then, the window was closed by our ok-button and not by upper-right-corner-X, so we have to destroy the window by ourself
1376         gtk_widget_destroy(dialog);
1377 	}
1378 	myWrap_gdk_threads_leave("getSizeOfSelectedItemsRecursive_dialog3 ");
1379 
1380 	//free everything in the struct and the struct itself
1381 	free(stru->ibreak);
1382 	if (stru->gstrPath != NULL){
1383 		g_string_free(stru->gstrPath,TRUE);
1384 	}
1385 	for (i=0; i<stru->ItemStringCounter; i++){
1386 		g_string_free(stru->gstrDPItems[i], TRUE);
1387 	}
1388     free(stru->gstrDPItems);
1389 	free(stru->intPSizes);
1390 	free(stru->intPTypes);
1391 	free(stru);
1392 	stru = NULL;
1393 	g_string_free(gstrBuf,TRUE);
1394 	g_string_free(gstrBuf2, TRUE);
1395 
1396 	TRACEIT(10,"getSizeOfSelectedItemsRecursive_dialog		ends");
1397 	g_thread_exit(0);
1398 }
1399 
1400 
getDirectorySize(guint64 * size,GString * gstrDirectory,int * ibreak,gboolean bFollowLinks)1401 int getDirectorySize(guint64 *size, GString *gstrDirectory, int *ibreak, gboolean bFollowLinks){
1402     //calls openLocation which is thread save in here, because this function is called
1403     //only from other threads
1404     //stops when ibreak == 1
1405 	TRACEIT(10,"getDirectorySize		start");
1406 	if (size == NULL || gstrDirectory == NULL || ibreak == NULL){
1407         TRACEIT(2,"getDirectorySize		end, Parameter NULL");
1408         return -1;
1409 	}
1410 	if (FALSE == g_file_test( gstrDirectory->str, G_FILE_TEST_EXISTS)){
1411         TRACEIT(2,"getDirectorySize		end, error opening item:");
1412         return -1;
1413 	}
1414 	GString *gstrNames = g_string_new(gstrDirectory->str);
1415 	GString *Path= g_string_new(gstrDirectory->str);
1416 	struct FileAttributs attribs;
1417     struct myLocationStruct locationStru;
1418     int iFoundLink = 0;
1419 
1420     //check if we have an Directory
1421     if (FALSE == checkStringIsPath( gstrDirectory->str )){ //then we have no directory
1422         checkPathForLastCharOtherwise(gstrNames);
1423         getLastStringInPath(gstrNames);
1424         GetPathFromPathWithName(Path, 1);
1425         if (strcmp(gstrNames->str,".")!=0 && strcmp(gstrNames->str,"..")!=0){
1426             fileAttributesGet( &attribs, Path->str, gstrNames->str);
1427             if (attribs.gstrLinkTarget){
1428                 g_string_free(attribs.gstrLinkTarget, TRUE);
1429             }
1430             *size+=attribs.size;
1431         }
1432         g_string_free(gstrNames,TRUE);
1433         g_string_free(Path,TRUE);
1434         TRACEIT(10,"getDirectorySize		end");
1435         return 0;
1436     }
1437 
1438 	if (0 != openLocation(gstrDirectory->str, &locationStru, FALSE, TRUE)){
1439 	    closeLocation(&locationStru);
1440 	    g_string_free(gstrNames,TRUE);
1441         g_string_free(Path,TRUE);
1442         TRACEIT(2,"getDirectorySize		end, could not open directory");
1443         return -1;
1444     }
1445 
1446 	while ( 1 == getNextItemInLocation(&locationStru, gstrNames, FALSE, TRUE) && *ibreak == 0){
1447 
1448 		//fileAttributesGet(dirzeiger, DirectoryOpened, &attribs, gstrDirectory->str, gstrNames->str);
1449 		fileAttributesGet(&attribs, gstrDirectory->str, gstrNames->str);
1450 		if (attribs.gstrLinkTarget){
1451             iFoundLink = 1;
1452             g_string_free(attribs.gstrLinkTarget, TRUE);
1453 		}
1454 		if (strcmp(gstrNames->str,".")!=0 && strcmp(gstrNames->str,"..")!=0 &&  ( attribs.type_d==4 && (iFoundLink!=1 || bFollowLinks==TRUE ) ) ){
1455 			g_string_assign(Path,gstrDirectory->str);
1456 			checkPathForLastChar(Path);
1457 			g_string_append(Path,gstrNames->str);
1458 			getDirectorySize(size, Path, ibreak, bFollowLinks);
1459 		}
1460 		else if (strcmp(gstrNames->str,".")!=0 && strcmp(gstrNames->str,"..")!=0){
1461 			*size+=attribs.size;
1462 		}
1463 	}
1464 
1465 	//S�ubern:
1466 	closeLocation(&locationStru);
1467 	g_string_free(gstrNames,TRUE);
1468 	g_string_free(Path,TRUE);
1469 
1470     TRACEIT(10,"getDirectorySize		end");
1471     if (*ibreak == 0){
1472         return 0;
1473     }
1474     else{
1475         return -1;
1476     }
1477 }
1478 
1479 
markedNamesToClipboard_Helper(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)1480 static void markedNamesToClipboard_Helper(GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter,gpointer data){
1481 	TRACEIT(11,"markedNamesToClipboard_Helper		start");
1482 	if (data == NULL){
1483 		TRACEIT(2,"markedNamesToClipboard_Helper		end, PARAMETER NULL");
1484 		return;
1485 	}
1486 	struct AllInformationAllUseStruct *stru = (struct AllInformationAllUseStruct *)data;
1487 	gchar *Name=NULL;
1488 	gchar *Path=NULL;
1489 
1490 	GString *gstrNames = (GString *)stru->Info_1;
1491 	int iColumnName = *(int *)stru->Info_2;
1492 	gboolean bWithPath = *(gboolean *)stru->Info_3;
1493 	int iColumnPath = *(int *)stru->Info_4;
1494 	char *cpPath = (char *)stru->Info_5;
1495 
1496 	gtk_tree_model_get(model, iter, iColumnName, &Name, -1);
1497 
1498 	if (gstrNames->len != 0){
1499 		g_string_append(gstrNames, " ");
1500 	}
1501 
1502 	if (bWithPath == TRUE){
1503 		if (cpPath != NULL){
1504 			g_string_append(gstrNames, cpPath);
1505 		}
1506 		else if (iColumnPath > -1){
1507 			gtk_tree_model_get(model, iter, iColumnPath, &Path, -1);
1508 			g_string_append(gstrNames, Path);
1509 		}
1510 		else{
1511 			TRACEIT(2,"markedNamesToClipboard_Helper		parameter validation error");
1512 		}
1513 		checkPathForLastChar(gstrNames);
1514 	}
1515 
1516 	g_string_append(gstrNames, Name);
1517 
1518 	if (Name)
1519 		g_free(Name);
1520 	if (Path)
1521 		g_free(Path);
1522 
1523 	TRACEIT(11,"markedNamesToClipboard_Helper		end");
1524 }
1525 
1526 
markedNamesToClipboard(GtkTreeView * TreeView,gboolean bWithPath,int iColumnName,int iColumnPath,char * cpPath)1527 void markedNamesToClipboard(GtkTreeView *TreeView, gboolean bWithPath, int iColumnName, int iColumnPath, char *cpPath){
1528 	//copies the names marked in the TreeView to the real clipboard, if more than one item is marked, all names are copied to one single line
1529 	//if bWithPath is TRUE, the pathes are added to the names.
1530 	//if bWithPath is FALSE, only the names are copied
1531 	//the names are searched in the column iColumnName
1532 	//when bWithPath is TRUE, iColumnPath or cpPath must be valid. cpPath is checked for NULL, iColumnPath is checked for < 0
1533 	TRACEIT(10,"markedNamesToClipboard		start");
1534 	GtkTreeSelection	*selection;
1535 	struct AllInformationAllUseStruct stru;
1536 	GString *gstrNames=NULL;
1537 	GtkClipboard *ClipBoard=NULL;
1538 
1539 	if (TreeView == NULL){
1540 		TRACEIT(2,"markedNamesToClipboard		end, PARAMETER NULL");
1541 		return;
1542 	}
1543 
1544 	//validate:
1545 	if (bWithPath == TRUE && cpPath==NULL && iColumnPath<0){
1546 		TRACEIT(2,"markedNamesToClipboard		end, parameter validation error");
1547 		return;
1548 	}
1549 
1550 	gstrNames = g_string_sized_new(10);
1551 	stru.Info_1 = (void *)gstrNames;
1552 	stru.Info_2 = (void *)&iColumnName;
1553 	stru.Info_3 = (void *)&bWithPath;
1554 	stru.Info_4 = (void *)&iColumnPath;
1555 	stru.Info_5 = (void *)cpPath;
1556 
1557 	selection  = gtk_tree_view_get_selection(TreeView);
1558 	gtk_tree_selection_selected_foreach(selection, markedNamesToClipboard_Helper, (void *)&stru);
1559 
1560 	//printf("gstrNames = %s\nlen=%d\n",gstrNames->str, gstrNames->len);
1561 
1562 	ClipBoard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1563 	if (ClipBoard != NULL){
1564 		gtk_clipboard_set_text (ClipBoard, gstrNames->str, gstrNames->len);
1565 	}
1566 	else{
1567 		TRACEIT(2,"markedNamesToClipboard		end, could not achive clipboard object");
1568 	}
1569 
1570 	if (gstrNames)
1571 		g_string_free(gstrNames, TRUE);
1572 
1573 	TRACEIT(10,"markedNamesToClipboard		end");
1574 }
1575 
1576 
mySelectAllFunction_Helper(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)1577 static void mySelectAllFunction_Helper(GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter,gpointer data){
1578     //if (gtk_tree_model_get_iter(model, iter, path)){
1579     TRACEIT(10,"mySelectAllFunction_Helper		start");
1580 
1581     // 1'st POSSIBILITY
1582     struct AllInformationAllUseStruct *stru = (struct AllInformationAllUseStruct *)data;
1583     GtkTreeSelection **selection = (GtkTreeSelection **)stru->Info_2;
1584 	int *found = (int *)stru->Info_1;
1585 	if (*found >= 2){
1586 	    TRACEIT(10,"mySelectAllFunction_Helper		end, . and .. already found");
1587         return;
1588 	}
1589     gchar *Name=NULL;
1590 	gtk_tree_model_get(model, iter, COL_NAME, &Name, -1);
1591 
1592 	if ((strcmp(Name, "..")==0 || strcmp(Name,".")==0)){
1593         (*found)+=1;
1594         gtk_tree_selection_unselect_iter(*selection, iter);
1595 	}
1596 
1597     if (Name)
1598         g_free(Name);
1599         // END 1'st POSSIBILITY
1600 
1601 /*
1602 
1603     // 2'st POSSIBILITY
1604     gchar *Name=NULL;
1605     GtkTreeSelection **selection = (GtkTreeSelection **)data;
1606     gtk_tree_model_get(model, iter, COL_NAME, &Name, -1);
1607     //gtk_tree_model_get(model, iter, COL_NAME, &Name, -1);
1608     if (Name != NULL && !(strcmp(Name, "..")==0 || strcmp(Name,".")==0)){
1609         gtk_tree_selection_select_iter(*selection, iter);
1610 	}
1611     if (Name)
1612         g_free(Name);
1613     // END 2'st POSSIBILITY
1614 */
1615     TRACEIT(10,"mySelectAllFunction_Helper		end");
1616 }
1617 
1618 
mySelectAllFunction(GtkTreeView * treeview,gpointer user_data)1619 gboolean mySelectAllFunction( GtkTreeView *treeview, gpointer user_data){
1620     //catches the signel select-all from within the listviews (side views only)
1621     TRACEIT(10,"mySelectAllFunction		start");
1622 
1623     // 1'st POSSIBILITY
1624     GtkTreeSelection	*selection;
1625     struct AllInformationAllUseStruct stru;
1626     int found=0;
1627     stru.Info_1 = (void *)&found;
1628     stru.Info_2 = (void *)&selection;
1629     stru.Info_3 = NULL;
1630     stru.Info_4 = NULL;
1631     stru.Info_5 = NULL;
1632 
1633     selection  = gtk_tree_view_get_selection(treeview);
1634     gtk_tree_selection_select_all ( selection );
1635     gtk_tree_selection_selected_foreach(selection, mySelectAllFunction_Helper, (void *)&stru);
1636     // END 1'st POSSIBILITY
1637 
1638 
1639 /*
1640     // 2'st POSSIBILITY
1641     GtkTreeSelection *selection;    // Tested within the library directory with more than 200 entries: this solution is realy slow!!
1642     selection = gtk_tree_view_get_selection(treeview);
1643     struct SideObjectList *Object = (struct SideObjectList *)user_data;
1644     gtk_tree_model_foreach(GTK_TREE_MODEL(Object->listStore),(GtkTreeModelForeachFunc) mySelectAllFunction_Helper,(void *)&selection);
1645     // END 2'st POSSIBILITY
1646 */
1647     TRACEIT(10,"mySelectAllFunction		end");
1648     return TRUE;
1649 }
1650 
1651 
markItemsWithSameType_Helper_1(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)1652 static void markItemsWithSameType_Helper_1(GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter,gpointer data){
1653 	TRACEIT(11,"markItemsWithSameType_Helper_1		start");
1654 
1655     struct AllInformationAllUseStruct *stru = (struct AllInformationAllUseStruct *)data;
1656 	struct updateList **typeList=(struct updateList **)stru->Info_1;
1657 	int *ColType = stru->Info_2;
1658 
1659 	gchar *type=NULL;
1660 	gchar *typebuf=NULL;
1661 
1662     gtk_tree_model_get(model, iter, *ColType,&type, -1);
1663 
1664     typebuf = g_utf8_strdown(type,-1);
1665     if (*typeList != NULL){
1666         if (0==updateList_checkForItem_NoRef(typeList, typebuf)){
1667             updateList_addItem(typeList, typebuf, NULL, NULL, 0);
1668         }
1669     }
1670     else{
1671         updateList_addItem(typeList, typebuf, NULL, NULL, 0);
1672     }
1673 
1674     if (type)
1675         g_free(type);
1676     if (typebuf)
1677         g_free(typebuf);
1678 	TRACEIT(11,"markItemsWithSameType_Helper_1		end");
1679 }
1680 
1681 
markItemsWithSameType_Helper_2(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)1682 static void markItemsWithSameType_Helper_2(GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter,gpointer data){
1683 	TRACEIT(11,"markItemsWithSameType_Helper_2		start");
1684 
1685     struct AllInformationAllUseStruct *stru = (struct AllInformationAllUseStruct *)data;
1686 	struct updateList **typeList=(struct updateList **)stru->Info_1;
1687 	int *ColType = stru->Info_2;
1688 	GtkTreeSelection *selection = (GtkTreeSelection *)stru->Info_3;
1689 
1690 	gchar *type=NULL;
1691 	gchar *typebuf=NULL;
1692 
1693     gtk_tree_model_get(model, iter, *ColType,&type, -1);
1694 
1695     typebuf = g_utf8_strdown(type,-1);
1696     struct updateList *bufList = *typeList;
1697     updateList_getFirstItem(&bufList);
1698 
1699     if (0==updateList_checkForItem_NoRef(&bufList, typebuf)){
1700         gtk_tree_selection_unselect_iter(selection, iter);
1701     }
1702 
1703     if (type)
1704         g_free(type);
1705     if (typebuf)
1706         g_free(typebuf);
1707 	TRACEIT(11,"markItemsWithSameType_Helper_2		end");
1708 }
1709 
1710 
markItemsWithSameType(GtkTreeView * treeview,int ColType)1711 void markItemsWithSameType(GtkTreeView *treeview, int ColType){
1712     //selects all items in treeview wich are from the same type as the already marked one.
1713     //ColType holds the ID of the coloumn with the type information
1714 
1715 
1716     //get the types of all marked items and put them to in a list
1717     struct AllInformationAllUseStruct stru;
1718     struct updateList *typeList=NULL;
1719 
1720     stru.Info_1 = (void *)&typeList;
1721     stru.Info_2 = (void *)&ColType;
1722 
1723     GtkTreeSelection *selection;
1724 	selection = gtk_tree_view_get_selection(treeview);
1725 	gtk_tree_selection_selected_foreach(selection, markItemsWithSameType_Helper_1, (void *)&stru);
1726 
1727     //The list is ready, now mark all items and walk throught the view and unmark the right ones.
1728     stru.Info_3 = (void *)selection;
1729     gtk_tree_selection_select_all(selection);
1730 
1731     gtk_tree_selection_selected_foreach(selection, markItemsWithSameType_Helper_2, (void *)&stru);
1732 
1733 
1734     //now the . and .. may be marked: check this
1735     int found=0;
1736     stru.Info_1 = (void *)&found;
1737     stru.Info_2 = (void *)&selection;
1738     gtk_tree_selection_selected_foreach(selection, mySelectAllFunction_Helper, (void *)&stru);
1739 
1740     updateList_deleteList(&typeList);
1741 
1742 }
1743 
1744