1 /*
2  * Copyright (C) 2002-2012 Edscott Wilson Garcia
3  * EMail: edscott@users.sf.net
4  *
5  *
6  * This program 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  * This program 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 this program;
18  */
19 
20 //////////////////////////////////////////////////////////////////////7
21 
22 #define RFM_PRIMARY_LAYOUT_C
23 
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27 
28 #include "rfm.h"
29 #include "rfm_modules.h"
30 
31 static GtkAllocation rfm_allocation;
rfm_get_allocation(void)32 GtkAllocation *rfm_get_allocation(void){return &rfm_allocation;}
rfm_set_allocation(void)33 void rfm_set_allocation(void){
34     rfm_global_t *rfm_global_p = rfm_global();
35     gtk_widget_get_allocation (rfm_global_p->window,&rfm_allocation);
36    // nested in hpane...
37    GtkWidget *hpane = g_object_get_data(G_OBJECT(rfm_global_p->window), "hpane");
38    if (hpane){
39         NOOP(stderr, "signal_on_size_paper(): we are nested in an hpane...%d\n",
40                 gtk_paned_get_position (GTK_PANED(hpane)));
41         rfm_allocation.width -= gtk_paned_get_position (GTK_PANED(hpane));
42     }
43     //memcpy(&rfm_allocation, &allocation, sizeof(GtkAllocation));
44     return;
45 }
46 
47 static const gchar *font_sizes_v[] = {
48     "6",
49     "8",
50     "9",
51     "10",
52     "11",
53     "12",
54     "14",
55     "18",
56     "20",
57     "22",
58     "24",
59     NULL
60 };
61 
62 static const gchar *icon_sizes_v[] = {
63     "Normal",
64     "Details",
65     "Compact",
66     "Big",
67     "Huge",
68     NULL
69 };
70 
71 #include "primary-layout.i"
72 
rfm_get_icon_sizes(void)73 const gchar **rfm_get_icon_sizes(void){return icon_sizes_v;}
rfm_get_font_sizes(void)74 const gchar **rfm_get_font_sizes(void){return font_sizes_v;}
75 
76 #define LAYOUT_ICON_SIZE (0x01)
77 #define LAYOUT_VPANE_ALLOCATION (0x01<<1)
78 #define LAYOUT_CELLWIDTH (0x01<<2)
79 #define LAYOUT_CELLHEIGHT (0x01<<3)
80 #define LAYOUT_ROOT_PARAMETERS (0x01<<4)
81 #define LAYOUT_ROOT_CONFIGURED (0x01<<5)
82 
83 void
rfm_layout_population_grid_row(view_t * view_p,population_t * population_p,gint element)84 rfm_layout_population_grid_row (view_t * view_p, population_t *population_p, gint element){
85     gint grid_rows = GRID_ROWS(view_p);
86     gint grid_columns = GRID_COLUMNS(view_p);
87     if (view_p->flags.type == ICONVIEW_TYPE) {
88 	if(grid_columns) {
89 	    population_p->row = element / grid_columns;
90 	    population_p->column = element % grid_columns;
91 	} else {
92 	    population_p->row = 0;
93 	    population_p->column = element;
94 	}
95     } else { // transposed matrix for desktop
96 	if(grid_rows) {
97 	    population_p->row = element % grid_rows;
98 	    population_p->column = element / grid_rows;
99 	} else {
100 	    population_p->row = element;
101 	    population_p->column = 0;
102 	}
103     }
104 }
105 
rfm_layout_get_name_width(view_t * view_p)106 gint rfm_layout_get_name_width(view_t *view_p){
107     if (!view_p) return FALSE;
108     view_layout_t *view_layout_p = &(view_p->view_layout);
109     return view_layout_p->name_width;
110 }
111 
rfm_layout_get_text_height(view_t * view_p)112 gint rfm_layout_get_text_height(view_t *view_p){
113     if (!view_p) return FALSE;
114     view_layout_t *view_layout_p = &(view_p->view_layout);
115     return view_layout_p->text_height;
116 }
117 
rfm_layout_set_root_width(view_t * view_p,gint value)118 gint rfm_layout_set_root_width(view_t *view_p, gint value){
119     if (!view_p) return FALSE;
120     view_layout_t *view_layout_p = &(view_p->view_layout);
121     return view_layout_p->root_w = value;
122 }
123 
rfm_layout_set_root_height(view_t * view_p,gint value)124 gint rfm_layout_set_root_height(view_t *view_p, gint value){
125     if (!view_p) return FALSE;
126     view_layout_t *view_layout_p = &(view_p->view_layout);
127     return view_layout_p->root_h = value;
128 }
129 
rfm_layout_get_root_width(view_t * view_p)130 gint rfm_layout_get_root_width(view_t *view_p){
131     if (!view_p) return FALSE;
132     view_layout_t *view_layout_p = &(view_p->view_layout);
133     return view_layout_p->root_w;
134 }
135 
rfm_layout_get_root_height(view_t * view_p)136 gint rfm_layout_get_root_height(view_t *view_p){
137     if (!view_p) return FALSE;
138     view_layout_t *view_layout_p = &(view_p->view_layout);
139     return view_layout_p->root_h;
140 }
141 
rfm_layout_get_root_depth(view_t * view_p)142 gint rfm_layout_get_root_depth(view_t *view_p){
143     if (!view_p) return FALSE;
144     view_layout_t *view_layout_p = &(view_p->view_layout);
145     return view_layout_p->root_d;
146 }
147 
rfm_layout_get_max_elements(view_t * view_p)148 gint rfm_layout_get_max_elements(view_t *view_p){
149     if (!view_p) return FALSE;
150     view_layout_t *view_layout_p = &(view_p->view_layout);
151     return view_layout_p->max_elements;
152 }
153 
rfm_layout_set_margin_top(view_t * view_p,gint value)154 gint rfm_layout_set_margin_top(view_t *view_p, gint value){
155     if (!view_p) return FALSE;
156     view_layout_t *view_layout_p = &(view_p->view_layout);
157     return view_layout_p->margin_top = value;
158 }
159 
rfm_layout_set_margin_bottom(view_t * view_p,gint value)160 gint rfm_layout_set_margin_bottom(view_t *view_p, gint value){
161     if (!view_p) return FALSE;
162     view_layout_t *view_layout_p = &(view_p->view_layout);
163     return view_layout_p->margin_bottom = value;
164 }
165 
rfm_layout_set_margin_right(view_t * view_p,gint value)166 gint rfm_layout_set_margin_right(view_t *view_p, gint value){
167     if (!view_p) return FALSE;
168     view_layout_t *view_layout_p = &(view_p->view_layout);
169     return view_layout_p->margin_right = value;
170 }
171 
rfm_layout_set_margin_left(view_t * view_p,gint value)172 gint rfm_layout_set_margin_left(view_t *view_p, gint value){
173     if (!view_p) return FALSE;
174     view_layout_t *view_layout_p = &(view_p->view_layout);
175     return view_layout_p->margin_left = value;
176 }
177 
178 
rfm_layout_get_margin_top(view_t * view_p)179 gint rfm_layout_get_margin_top(view_t *view_p){
180     if (!view_p) return FALSE;
181     view_layout_t *view_layout_p = &(view_p->view_layout);
182     return view_layout_p->margin_top;
183 }
184 
rfm_layout_get_margin_bottom(view_t * view_p)185 gint rfm_layout_get_margin_bottom(view_t *view_p){
186     if (!view_p) return FALSE;
187     view_layout_t *view_layout_p = &(view_p->view_layout);
188     return view_layout_p->margin_bottom;
189 }
190 
rfm_layout_get_margin_right(view_t * view_p)191 gint rfm_layout_get_margin_right(view_t *view_p){
192     if (!view_p) return FALSE;
193     view_layout_t *view_layout_p = &(view_p->view_layout);
194     return view_layout_p->margin_right;
195 }
196 
rfm_layout_get_margin_left(view_t * view_p)197 gint rfm_layout_get_margin_left(view_t *view_p){
198     if (!view_p) return FALSE;
199     view_layout_t *view_layout_p = &(view_p->view_layout);
200     return view_layout_p->margin_left;
201 }
202 
203 
rfm_layout_is_setup(view_t * view_p)204 gboolean rfm_layout_is_setup(view_t *view_p){
205     if (!view_p) {
206 	DBG("rfm_layout_is_setup(): !view_p\n");
207 	return FALSE;
208     }
209     view_layout_t *view_layout_p = &(view_p->view_layout);
210     if (!(view_layout_p->tripwire & LAYOUT_ICON_SIZE)) {
211 	DBG("rfm_layout_is_setup(): LAYOUT_ICON_SIZE\n");
212 	return FALSE;
213     }
214     GtkWidget *vpane = g_object_get_data(G_OBJECT(view_p->widgets.paper), "vpane");
215     if (vpane && !(view_layout_p->tripwire & LAYOUT_VPANE_ALLOCATION)) {
216 	DBG("rfm_layout_is_setup(): LAYOUT_VPANE_ALLOCATION\n");
217 	return FALSE;
218     }
219     if (!(view_layout_p->tripwire & LAYOUT_CELLWIDTH)) {
220 	TRACE("rfm_layout_is_setup(): LAYOUT_CELLWIDTH\n");
221 	return FALSE;
222     }
223     if (!(view_layout_p->tripwire & LAYOUT_CELLHEIGHT)) {
224 	DBG("rfm_layout_is_setup(): LAYOUT_CELLHEIGHT\n");
225 	return FALSE;
226     }
227     if (!(view_layout_p->tripwire & LAYOUT_ROOT_PARAMETERS)) {
228 	DBG("rfm_layout_is_setup(): LAYOUT_ROOT_PARAMETERS\n");
229 	return FALSE;
230     }
231     if (!(view_layout_p->tripwire & LAYOUT_ROOT_CONFIGURED)) {
232 	DBG("rfm_layout_is_setup(): LAYOUT_ROOT_CONFIGURED\n");
233 	return FALSE;
234     }
235     return TRUE;
236 }
237 
238 
rfm_layout_get_grid_rows(view_t * view_p)239 gint rfm_layout_get_grid_rows(view_t *view_p){
240     if (!view_p) g_error("rfm_layout_get_grid_rows: !view_p\n");
241     view_layout_t *view_layout_p = &(view_p->view_layout);
242     if (!(view_layout_p->tripwire & LAYOUT_ROOT_CONFIGURED))
243 	g_error("rfm_layout_get_grid_rows: view_layout_p item LAYOUT_ROOT_CONFIGURED is not set\n");
244     return view_layout_p->grid_rows;
245 }
246 
rfm_layout_get_grid_columns(view_t * view_p)247 gint rfm_layout_get_grid_columns(view_t *view_p){
248     if (!view_p) g_error("rfm_layout_get_grid_colums: !view_p\n");
249     view_layout_t *view_layout_p = &(view_p->view_layout);
250     if (!(view_layout_p->tripwire & LAYOUT_ROOT_CONFIGURED))
251 	g_error("rfm_layout_get_grid_colums: view_layout_p item LAYOUT_ROOT_CONFIGURED is not set\n");
252     return view_layout_p->grid_columns;
253 }
254 
layout_set_root_parameters(void * data)255 static void *layout_set_root_parameters(void *data){
256     view_t *view_p = data;
257     gint width;
258     gint height;
259     gint depth;
260     rfm_global_t *rfm_global_p = rfm_global();
261     rfm_get_drawable_geometry (rfm_global_p->root_Xwindow, NULL, NULL,
262 	    &width, &height, &depth);
263     view_layout_t *view_layout_p = &(view_p->view_layout);
264     view_layout_p->root_w = width;
265     view_layout_p->root_h = height;
266     view_layout_p->root_d = depth;
267     return NULL;
268 }
269 
rfm_layout_set_root_parameters(view_t * view_p)270 void rfm_layout_set_root_parameters(view_t *view_p){
271     if (!view_p) g_error("rfm_layout_set_root_parameters: !view_p\n");
272     view_layout_t *view_layout_p = &(view_p->view_layout);
273     //rfm_global_t *rfm_global_p = rfm_global();
274     if (rfm_get_gtk_thread() != g_thread_self()){
275 	rfm_context_function(layout_set_root_parameters, view_p);
276     } else {
277 	layout_set_root_parameters(view_p);
278     }
279     view_layout_p->tripwire |= LAYOUT_ROOT_PARAMETERS;
280     return;
281 }
282 
rfm_layout_get_root_parameters(view_t * view_p,gint * width,gint * height,gint * depth)283 void rfm_layout_get_root_parameters(view_t *view_p, gint *width, gint *height, gint *depth){
284     if (!view_p) g_error("rfm_layout_get_root_parameters: !view_p\n");
285     view_layout_t *view_layout_p = &(view_p->view_layout);
286     if (!(view_layout_p->tripwire & LAYOUT_ROOT_PARAMETERS))
287 	g_error("rfm_layout_get_root_parameters: view_layout_p item LAYOUT_ROOT_PARAMETERS is not set\n");
288     if (width) *width = view_layout_p->root_w;
289     if (height) *height = view_layout_p->root_h;
290     if (depth) *depth = view_layout_p->root_d;
291     return;
292 }
293 
rfm_layout_get_icon_size(view_t * view_p)294 gint rfm_layout_get_icon_size(view_t *view_p){
295     if (!view_p) g_error("rfm_layout_get_cellheight: !view_p\n");
296     view_layout_t *view_layout_p = &(view_p->view_layout);
297     if (!(view_layout_p->tripwire & LAYOUT_ICON_SIZE))
298 	g_error("rfm_layout_get_icon_size: view_layout_p item LAYOUT_ICON_SIZE is not set\n");
299     if (view_layout_p->icon_size) return view_layout_p->icon_size;
300     return TINY_ICON_SIZE;
301 }
302 
rfm_layout_get_icon_size_id(view_t * view_p)303 gint rfm_layout_get_icon_size_id(view_t *view_p){
304     if (!view_p) g_error("rfm_layout_get_cellheight: !view_p\n");
305     view_layout_t *view_layout_p = &(view_p->view_layout);
306     if (!(view_layout_p->tripwire & LAYOUT_ICON_SIZE))
307 	g_error("rfm_layout_get_icon_size: view_layout_p item LAYOUT_ICON_SIZE is not set\n");
308     return view_layout_p->icon_size;
309 }
310 
rfm_layout_is_details_size(view_t * view_p)311 gboolean rfm_layout_is_details_size(view_t *view_p){
312     if (!view_p) g_error("rfm_layout_get_cellheight: !view_p\n");
313     view_layout_t *view_layout_p = &(view_p->view_layout);
314     if (!(view_layout_p->tripwire & LAYOUT_ICON_SIZE))
315 	g_error("rfm_layout_get_icon_size: view_layout_p item LAYOUT_ICON_SIZE is not set\n");
316     if (view_layout_p->icon_size) return FALSE;
317     return TRUE;
318 }
319 
rfm_layout_get_cellheight(view_t * view_p)320 gint rfm_layout_get_cellheight(view_t *view_p){
321     if (!view_p) g_error("rfm_layout_get_cellheight: !view_p\n");
322     view_layout_t *view_layout_p = &(view_p->view_layout);
323     if (!(view_layout_p->tripwire & LAYOUT_CELLHEIGHT))
324 	g_error("rfm_layout_get_cellheight: view_layout_p item LAYOUT_CELLHEIGHT is not set\n");
325     return view_layout_p->cellheight;
326 }
327 
rfm_layout_get_cellwidth(view_t * view_p)328 gint rfm_layout_get_cellwidth(view_t *view_p){
329     if (!view_p) g_error("rfm_layout_get_cellwidth: !view_p\n");
330     view_layout_t *view_layout_p = &(view_p->view_layout);
331     if (!(view_layout_p->tripwire & LAYOUT_CELLWIDTH))
332 	g_error("rfm_layout_get_cellwidth: view_layout_p item LAYOUT_CELLWIDTH is not set\n");
333     return view_layout_p->cellwidth;
334 }
335 
336 static void *
get_drawable_geometry_f(void * data)337 get_drawable_geometry_f(void *data){
338     void **arg = data;
339     Drawable drawable = GPOINTER_TO_INT(arg[0]);
340     gint *x = (gint *)arg[1];
341     gint *y = (gint *)arg[2];
342     gint *w = (gint *)arg[3];
343     gint *h = (gint *)arg[4];
344     gint *d = (gint *)arg[5];
345 
346     rfm_global_t *rfm_global_p = rfm_global();
347     if (rfm_get_gtk_thread() != g_thread_self()){
348 	g_error("rfm_get_drawable_geometry is a main thread function\n");
349     }
350     gint x_return, y_return;
351     guint w_return, h_return, d_return, border_return;
352     Window root_return;
353     Display *display;
354     if (rfm_global_p) display = rfm_global_p->Xdisplay;
355     else display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
356 
357     XGetGeometry(display, drawable, &root_return,
358 	    &x_return, &y_return,
359 	    &w_return, &h_return,
360 	    &border_return,
361 	    &d_return);
362     if (x) *x = x_return;
363     if (y) *y = y_return;
364     if (w) *w = w_return;
365     if (h) *h = h_return;
366     if (d) *d = d_return;
367     return NULL;
368 }
369 
rfm_get_drawable_geometry(Drawable drawable,gint * x,gint * y,gint * w,gint * h,gint * d)370 void rfm_get_drawable_geometry(Drawable drawable,
371 	gint *x, gint *y, gint *w, gint *h, gint *d){
372     void *arg[]={
373         GINT_TO_POINTER(drawable),
374         (void *) x,
375         (void *) y,
376         (void *) w,
377         (void *) h,
378         (void *) d,
379         NULL
380     };
381     rfm_context_function(get_drawable_geometry_f, arg);
382     return;
383 
384 }
385 #if 0
386 void rfm_get_drawable_geometry(Drawable drawable,
387 	gint *x, gint *y, gint *w, gint *h, gint *d){
388     rfm_global_t *rfm_global_p = rfm_global();
389     if (rfm_get_gtk_thread() != g_thread_self()){
390 	g_error("rfm_get_drawable_geometry is a main thread function\n");
391     }
392     gint x_return, y_return;
393     guint w_return, h_return, d_return, border_return;
394     Window root_return;
395     Display *display;
396     if (rfm_global_p) display = rfm_global_p->Xdisplay;
397     else display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
398 
399     XGetGeometry(display, drawable, &root_return,
400 	    &x_return, &y_return,
401 	    &w_return, &h_return,
402 	    &border_return,
403 	    &d_return);
404     if (x) *x = x_return;
405     if (y) *y = y_return;
406     if (w) *w = w_return;
407     if (h) *h = h_return;
408     if (d) *d = d_return;
409     return;
410 }
411 #endif
412 
413 gint
rfm_get_default_size(void)414 rfm_get_default_size(void){
415     gint default_size = -1;
416     const gchar *rfm_default_icon_size = getenv("RFM_DEFAULT_ICON_SIZE");
417     if (rfm_default_icon_size && strlen(rfm_default_icon_size) != 0){
418 	const gchar **p=icon_sizes_v;
419 	for (; p && *p; p++){
420 	    if (strcmp(*p, rfm_default_icon_size)==0){
421 		// Gotcha. If value is not valid, it will be ignored.
422 		if (strcmp(*p, "Normal")==0) {
423 		    default_size = SMALL_ICON_SIZE;
424 		} else
425 		if (strcmp(*p, "Compact")==0) {
426 		    default_size = TINY_ICON_SIZE;
427 		} else
428 		if (strcmp(*p, "Details")==0) {
429 		    default_size = LIST_ICON_SIZE;
430 		} else
431 		if (strcmp(*p, "Big")==0) {
432 		    default_size = MEDIUM_ICON_SIZE;
433 		} else
434 		if (strcmp(*p, "Huge")==0) {
435 		    default_size = BIG_ICON_SIZE;
436 		}
437 	    }
438 	}
439     }
440     // Fallback condition
441     if (default_size == -1) {
442 	NOOP("cannot determine default icon size\n");
443 	return SMALL_ICON_SIZE;
444     }
445     return default_size;
446 }
447 
448 static
449 view_preferences_t *
get_view_preferences_path(gint type,const gchar * path)450 get_view_preferences_path (gint type, const gchar * path) {
451     NOOP ("rodent_get_view_preferences()\n");
452     DBHashTable *preferences=NULL;
453     const gchar *key;
454     GString *gs;
455     gchar *f;
456     if (type==ICONVIEW_TYPE) {
457 	f = g_build_filename (GRID_PREFERENCES_FILE, NULL);
458     } else {
459 	f = g_build_filename (DESK_PREFERENCES_FILE, NULL);
460     }
461 
462     TRACE("opening %s...\n",f);
463     FILE *f_p = fopen(f,"r");
464     if (f_p){
465         fclose(f_p);
466         preferences = dbh_new (f, NULL, DBH_READ_ONLY|DBH_PARALLEL_SAFE|DBH_THREAD_SAFE);
467     }
468 
469     TRACE("open %s.\n",f);
470 
471     if(!preferences) {
472         NOOP ("Preferences table does not yet exist: %s\n", f);
473         g_free (f);
474         return NULL;
475     }
476     dbh_set_parallel_lock_timeout(preferences, 3);
477     dbh_mutex_lock(preferences);
478 
479     if(path){
480         key = path;
481     } else {
482         key = "RODENT_ROOT";
483     }
484     NOOP ("looking for preferences with key=%s\n", key);
485 
486     gs = g_string_new (key);
487     sprintf ((char *)DBH_KEY (preferences), "%10u", g_string_hash (gs));
488     g_string_free (gs, TRUE);
489 
490     view_preferences_t *view_preferences_p=NULL;
491     if(dbh_load (preferences)) {
492         view_preferences_p=
493 		(view_preferences_t *)malloc(sizeof(view_preferences_t));
494 	if (!view_preferences_p) g_error("malloc: %s\n", strerror(errno));
495 	memcpy (view_preferences_p, DBH_DATA (preferences),
496 		sizeof (view_preferences_t));
497 
498 	NOOP ("got preferences with key=%s  (preferences=0x%x, sort_column%d)\n",
499            key, view_preferences_p->preferences, view_preferences_p->sortcolumn);
500     }
501     dbh_mutex_unlock(preferences);
502     dbh_close (preferences);
503     g_free (f);
504     return view_preferences_p;
505 }
506 
507 
508 view_preferences_t *
rfm_get_view_preferences(gint type,record_entry_t * target_en)509 rfm_get_view_preferences (gint type, record_entry_t *target_en) {
510 
511     const gchar *key=NULL;
512     if (target_en) {
513 	if (target_en->module){
514 	    key=(const gchar *)rfm_void(PLUGIN_DIR, target_en->module,
515 		    "module_preferences_key");
516 	}
517 	if (!key) key=target_en->path;
518 
519     } else {
520 	key="RODENT_ROOT";
521     }
522     view_preferences_t *view_preferences_p = get_view_preferences_path (type, key);
523     return view_preferences_p;
524 }
525 
526 
527 void
rfm_save_view_preferences(view_t * view_p,record_entry_t * target_en)528 rfm_save_view_preferences (view_t * view_p, record_entry_t *target_en) {
529     view_preferences_t iconview_preferences;
530     DBHashTable *preferences=NULL;
531     GString *gs;
532     gchar *f;
533     const gchar *key=NULL;
534     if(!view_p)
535         return;
536 
537 	NOOP("rfm_save_view_preferences: %s\n", key);
538 
539     if(!target_en){
540         key = "RODENT_ROOT";
541     } else if (target_en->module) {
542         key=(const gchar *)rfm_void(PLUGIN_DIR, target_en->module, "module_preferences_key");
543 	NOOP("getting preferences key from module: %s\n", key);
544     }
545     if (!key){
546 	if (target_en->path==NULL){
547 	    key = "RODENT_ROOT";
548 	} else {
549 	    key = target_en->path;
550 	}
551     }
552 
553     if (view_p->flags.type==ICONVIEW_TYPE) {
554 	f = g_build_filename (GRID_PREFERENCES_FILE, NULL);
555     } else {
556 	f = g_build_filename (DESK_PREFERENCES_FILE, NULL);
557     }
558     gchar *tmp_f=NULL;
559 
560 
561     TRACE("opening %s...\n",f);
562     FILE *f_p = fopen(f,"r");
563     if (f_p){
564         fclose(f_p);
565         preferences = dbh_new (f, NULL, DBH_PARALLEL_SAFE|DBH_THREAD_SAFE);
566     }
567     if(!preferences) {
568         NOOP ("creating file: %s", f);
569 	tmp_f =g_strdup_printf("%s-%d", f, (gint)getpid());
570 	unsigned char keylength=11;
571         gchar *directory = g_path_get_dirname(f);
572         if (!g_file_test(directory, G_FILE_TEST_IS_DIR)){
573             g_mkdir_with_parents(directory, 0700);
574         }
575         g_free(directory);
576         preferences = dbh_new (f, &keylength, DBH_PARALLEL_SAFE|DBH_THREAD_SAFE|DBH_CREATE);
577     }
578     TRACE("open %s.\n",f);
579     if(!preferences) {
580         DBG ("cannot open file: %s\n", f);
581         g_free (f);
582         g_free (tmp_f);
583         return;
584     }
585     dbh_set_parallel_lock_timeout(preferences, 3);
586     dbh_mutex_lock(preferences);
587 
588     gs = g_string_new (key);
589     sprintf ((char *)DBH_KEY (preferences), "%10u", g_string_hash (gs));
590     g_string_free (gs, TRUE);
591 
592     view_layout_t *view_layout_p = &(view_p->view_layout);
593 
594     iconview_preferences.preferences = view_p->flags.preferences;
595     iconview_preferences.sortcolumn = view_p->flags.sortcolumn;
596     iconview_preferences.icon_size = view_layout_p->icon_size;
597     NOOP("saving iconsize = %d\n", iconview_preferences.icon_size);
598 
599     memcpy (DBH_DATA (preferences), &iconview_preferences, sizeof (view_preferences_t));
600     dbh_set_recordsize (preferences, sizeof (view_preferences_t));
601 
602     if(!dbh_update (preferences)) {
603         DBG ("!dbh_update(preferences)\n");
604     }
605     dbh_mutex_unlock(preferences);
606     dbh_close (preferences);
607     if (tmp_f){
608 	if (rename(tmp_f, f) < 0){
609 	    DBG("rename(%s, %s) failed: %s\n",
610 		    tmp_f, f, strerror(errno));
611 	}
612     }
613     NOOP ("saved preferences with key=%s iconsize=%d \n",
614 	    key, ICON_SIZE(view_p));
615     g_free (f);
616     g_free (tmp_f);
617     return;
618 }
619 
620 
621 void
rfm_set_view_preferences(view_t * view_p,view_preferences_t * view_preferences_p)622 rfm_set_view_preferences (view_t *view_p, view_preferences_t *view_preferences_p) {
623     if(!view_preferences_p){
624 	// No user defined preferences for the "path". We shall now
625     	// fall back to the default settings.
626 	NOOP( "default settings\n");
627 	if (view_p->en && IS_LOCAL_TYPE(view_p->en->type)){
628 	    view_p->flags.preferences = DEFAULT_VIEW_PREFERENCES;
629 	} else {
630 	    view_p->flags.preferences = DEFAULT_REMOTE_PREFERENCES;
631 	}
632 
633         view_p->flags.sortcolumn = DEFAULT_SORT_COLUMN;
634 	rfm_layout_set_icon_size(view_p, rfm_get_default_size());
635 	return;
636     }
637 
638     // We were successful in retrieving user preferences for the "path".
639     view_p->flags.preferences = view_preferences_p->preferences;
640     view_p->flags.sortcolumn = view_preferences_p->sortcolumn;
641     rfm_layout_set_icon_size(view_p, view_preferences_p->icon_size);
642     if (view_p->en) {
643 	if(view_p->flags.preferences & __SHOW_HIDDEN){
644 	    NOOP( "rfm_set_view_preferences: shows hidden...\n");
645 	    SET_SHOWS_HIDDEN (view_p->en->type);
646 	} else {
647 	    NOOP( "rfm_set_view_preferences: does *not* show hidden...\n");
648 	    UNSET_SHOWS_HIDDEN (view_p->en->type);
649 	}
650 	if(view_p->flags.preferences & __SHOW_IMAGES){
651 	    SET_SHOWS_IMAGES (view_p->en->type);
652 	} else {
653 	    UNSET_SHOWS_IMAGES (view_p->en->type);
654 	}
655 	SET_USER_PREFERENCES(view_p->flags.preferences);
656     }
657 
658     return;
659 }
660 
661 static void *
get_pango_layout_height(void * data)662 get_pango_layout_height(void *data)
663 {
664     if (rfm_get_gtk_thread() != g_thread_self()){
665 	DBG("get_pango_layout_height is a main thread function main=0x%x self=0x%x\n",GPOINTER_TO_INT(rfm_get_gtk_thread()), GPOINTER_TO_INT(g_thread_self()));
666     }
667     view_t *view_p = data;
668     if (!view_p->widgets.paper) g_error("view_p->widgets.paper is NULL\n");
669     PangoLayout *layout;
670     PangoRectangle logical_rect;
671     const gchar *tag = "RIDE A BIKE TODAY";
672     layout = gtk_widget_create_pango_layout (view_p->widgets.paper, tag);
673     layout_set_variable_font(layout);
674     pango_layout_get_pixel_extents (layout, NULL, &(logical_rect));
675     gint height = logical_rect.height;
676     g_object_unref (layout);
677     return GINT_TO_POINTER(height);
678 }
679 
680 static void *
set_paper_size(gpointer data)681 set_paper_size(gpointer data){
682     if (rfm_get_gtk_thread() != g_thread_self()){
683 	g_error("set_paper_size is a main thread function\n");
684     }
685     view_t *view_p = data;
686     view_layout_t *view_layout_p = &(view_p->view_layout);
687     NOOP(stderr, "********   set_paper_size: %d, %d\n",
688 	    view_layout_p->paperX, view_layout_p->paperY);
689     gtk_widget_set_size_request (view_p->widgets.paper, view_layout_p->paperX, view_layout_p->paperY);
690     g_object_set_data(G_OBJECT(view_p->widgets.paper), "paperX",
691 	    GINT_TO_POINTER(view_layout_p->paperX));
692     g_object_set_data(G_OBJECT(view_p->widgets.paper), "paperY",
693 	    GINT_TO_POINTER(view_layout_p->paperY));
694     return NULL;
695 }
696 
697 
698 static void *
context_sync(gpointer data)699 context_sync(gpointer data){
700     if (rfm_get_gtk_thread() != g_thread_self()){
701 	g_error("context_sync is a main thread function\n");
702     }
703     gdk_display_sync (gdk_display_get_default ());
704     while (gtk_events_pending()) gtk_main_iteration();
705     if (data) return data;
706     return NULL;
707 }
708 
709 
710 static void *
do_layout_f(void * data)711 do_layout_f(void *data){
712     void **arg = data;
713     view_t *view_p = arg[0];
714     population_t *population_p = arg[1];
715     if (population_p->layout == NULL) rfm_do_layout (view_p, population_p);
716     return NULL;
717 }
718 
719 //
720 void
rfm_layout_pango_layout_setup(view_t * view_p)721 rfm_layout_pango_layout_setup(view_t *view_p){
722     view_layout_t *view_layout_p = &(view_p->view_layout);
723     if (view_layout_p->icon_size > TINY_ICON_SIZE) return;
724 
725     // Get longest label:
726 
727     population_t **pp = view_p->population_pp;
728     gint max_length = 0;
729     population_t *population_p = NULL;
730     for (; pp && *pp; pp++){
731 	gchar *label = g_strdup((*pp)->label);
732 	if (label && strlen(label)>max_length) {
733 	    max_length = strlen(label);
734 	    population_p = *pp;
735 	}
736 	g_free(label);
737     }
738     if (population_p) {
739 	void *arg[]={view_p, population_p};
740 	rfm_context_function(do_layout_f, arg);
741 	view_layout_p->name_width = population_p->logical_rect.width;
742 	GdkRectangle rect;
743 	rfm_layout_get_vpane_allocation(view_p, &rect);
744 	view_layout_p->details_width = rect.width - view_layout_p->name_width;
745     }
746 
747     NOOP(stderr, "+++ rfm_layout_details_setup : name width=%d, detail width=%d\n",
748 		view_layout_p->name_width,view_layout_p->details_width);
749 }
750 
751 
752 void
rfm_layout_get_vpane_allocation(view_t * view_p,GdkRectangle * rect)753 rfm_layout_get_vpane_allocation(view_t *view_p, GdkRectangle *rect){
754     if (!view_p){
755         memset(rect, 0, sizeof(GdkRectangle));
756         DBG("rfm_layout_get_vpane_allocation(): view_p cannot be null.\n");
757         return;
758     }
759     view_layout_t *view_layout_p = &(view_p->view_layout);
760     if (view_p->flags.type == DESKVIEW_TYPE){
761 	rect->x = rect->y = 0;
762 	rect->width = view_layout_p->window_width;
763 	rect->height = view_layout_p->window_height;
764 	return;
765     }
766     if (!(view_layout_p->tripwire & LAYOUT_VPANE_ALLOCATION)){
767 	g_error("rfm_layout_get_vpane_allocation: LAYOUT_VPANE_ALLOCATION is not set\n");
768     }
769     if (!view_p || !rect) g_error("!view_p || !rect\n");
770     memcpy(rect, &(view_layout_p->vpane_allocation), sizeof(GdkRectangle));
771     return;
772 }
773 void
rfm_layout_set_vpane_allocation(view_t * view_p)774 rfm_layout_set_vpane_allocation(view_t *view_p){
775     if (rfm_get_gtk_thread() != g_thread_self())
776 	g_error("rfm_layout_set_vpane_allocation is a main thread function\n");
777     view_layout_t *view_layout_p = &(view_p->view_layout);
778     if (view_p->flags.type == DESKVIEW_TYPE) {
779 	view_layout_p->vpane_allocation.width = view_layout_p->window_width;
780 	view_layout_p->vpane_allocation.height = view_layout_p->window_height;
781 	return;
782     }
783     GtkWidget *vpane = g_object_get_data(G_OBJECT(view_p->widgets.paper), "vpane");
784     if (!vpane){
785 	// deskview should not have entered this function.
786 	g_error("rfm_layout_set_vpane_allocation: vpane==NULL\n");
787     }
788     gtk_widget_get_allocation (vpane, &(view_layout_p->vpane_allocation));
789     view_layout_p->tripwire |= LAYOUT_VPANE_ALLOCATION;
790 }
791 
792 // This function sets the iconsize scale in gridview windows to the
793 // size saved for the particular directory in the view.
794 void *
rfm_layout_set_icon_size_scale(void * data)795 rfm_layout_set_icon_size_scale(void * data){
796     view_t *view_p = data;
797     GtkWidget *size_scale = g_object_get_data(G_OBJECT(view_p->widgets.paper), "size_scale");
798     if (size_scale == NULL){
799 	return NULL;
800     }
801     gtk_range_set_value (GTK_RANGE(size_scale), view_p->view_layout.icon_size);
802     g_object_set_data(G_OBJECT(size_scale), "oldvalue", GINT_TO_POINTER(view_p->view_layout.icon_size));
803 
804     gint sizeid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(size_scale), "sizeid"));
805     if (!sizeid)
806         g_object_set_data(G_OBJECT(size_scale), "sizeid", GINT_TO_POINTER(1+ICON_SIZE_ID(view_p)));
807     else if (sizeid-1 != ICON_SIZE_ID(view_p)) {
808         gchar *t=NULL;
809         switch (ICON_SIZE_ID(view_p)){
810             case BIG_ICON_SIZE: t = g_strdup_printf(_("Huge (%sx%s)"), "96", "96"); break;
811             case MEDIUM_ICON_SIZE: t = g_strdup_printf(_("Large (%sx%s)"), "72", "72"); break;
812             case SMALL_ICON_SIZE: t = g_strdup_printf(_("Medium (%sx%s)"), "48", "48"); break;
813             case TINY_ICON_SIZE: t = g_strdup_printf(_("Small (%sx%s)"), "24", "24"); break;
814             case LIST_ICON_SIZE: t =  g_strdup(_("List View")); break;
815         }
816         rfm_diagnostics(&(view_p->widgets), "rodent",_("Icon size:")," ", t, "\n", NULL);
817         g_free(t);
818         g_object_set_data(G_OBJECT(size_scale), "sizeid", GINT_TO_POINTER(1+ICON_SIZE_ID(view_p)));
819     }
820 
821     return NULL;
822 }
823 
824 
825 void
rfm_layout_set_icon_size(view_t * view_p,gint size)826 rfm_layout_set_icon_size(view_t *view_p, gint size){
827     NOOP(stderr, "--- icon size set to %d\n", size);
828     switch (size){
829 	case BIG_ICON_SIZE:
830 	case MEDIUM_ICON_SIZE:
831 	case SMALL_ICON_SIZE:
832 	case TINY_ICON_SIZE:
833 	case LIST_ICON_SIZE:
834 	    break;
835 	default:
836 	    g_error("rfm_layout_set_icon_size: incorrect size (%d)\n", size);
837     }
838     view_layout_t *view_layout_p = &(view_p->view_layout);
839     view_layout_p->tripwire |= LAYOUT_ICON_SIZE;
840     view_layout_p->icon_size = size;
841 
842 }
843 
844 void
rfm_layout_set_icon_size_full(view_t * view_p,gint size)845 rfm_layout_set_icon_size_full(view_t *view_p, gint size){
846     if (!view_p) g_error("rfm_layout_set_icon_size_full: !view_p\n");
847     view_layout_t *view_layout_p = &(view_p->view_layout);
848     if (!view_layout_p->max_elements) g_error("rfm_layout_set_icon_size_full: !view_layout_p->max_elements\n");
849 
850     rfm_layout_set_icon_size(view_p, size);
851     // this should be set already... rfm_layout_set_vpane_allocation(view_p);
852     rfm_layout_configure(view_p, view_layout_p->max_elements);
853 }
854 
855 static void
layout_reset_columns(view_t * view_p)856 layout_reset_columns(view_t *view_p){
857     view_layout_t *view_layout_p = &(view_p->view_layout);
858 
859     // Set the column width (required for cellwidth)
860     if (view_layout_p->icon_size >= SMALL_ICON_SIZE) {
861 	view_layout_p->column_width = view_layout_p->icon_size * 2;
862     } else if (view_layout_p->icon_size >= TINY_ICON_SIZE) {
863 	view_layout_p->column_width = SMALL_ICON_SIZE * 4;
864     } else {
865 	if (view_p->flags.type == DESKVIEW_TYPE) {
866 	    view_layout_p->column_width = rfm_allocation.width -
867 	    view_layout_p->margin_right - view_layout_p->margin_left;
868 	} else {
869 	    view_layout_p->column_width = view_layout_p->vpane_allocation.width;
870 	}
871     }
872     // Set the text_height (required for cellheight)
873     if (rfm_get_gtk_thread() == g_thread_self()){
874 	view_layout_p->text_height = GPOINTER_TO_INT(get_pango_layout_height(view_p));
875     } else {
876 	view_layout_p->text_height = GPOINTER_TO_INT(rfm_context_function(get_pango_layout_height, view_p));
877     }
878 
879     // Now set cellwidth and cell height
880 
881     view_layout_p->cellwidth = view_layout_p->column_width;
882     if (view_layout_p->icon_size >= SMALL_ICON_SIZE){
883 	view_layout_p->cellheight = view_layout_p->icon_size + (2*(view_layout_p->text_height + TEXTSPACING));
884     } else {
885 	// icon_size may be zero for details, so use the hardcode value, TINY_ICON_SIZE.
886 	view_layout_p->cellheight = TINY_ICON_SIZE + TEXTSPACING;
887     }
888     view_layout_p->tripwire |= (LAYOUT_CELLWIDTH|LAYOUT_CELLHEIGHT);
889 
890     // Width is equal to window width, minus margin.
891     // Margin is (CELLWIDTH(view_p) / 2.
892     gint width = rfm_allocation.width - (view_layout_p->cellwidth / 2);
893 
894     // Now get number of grid rows and columns to fit view_layout_p->max_elements.
895     GtkWidget *vpane = g_object_get_data(G_OBJECT(view_p->widgets.paper), "vpane");
896     if (vpane == NULL) { // transposed...
897 	gint height = rfm_allocation.height -
898 	    view_layout_p->margin_bottom - view_layout_p->margin_top;
899 	width = rfm_allocation.width -
900 	    view_layout_p->margin_right - view_layout_p->margin_left;
901 
902 
903 	view_layout_p->grid_rows = ((double)height / view_layout_p->cellheight) + 0.5;
904 	view_layout_p->grid_columns = ((double)width / view_layout_p->cellwidth) + 0.5;
905 	if (view_layout_p->grid_rows * view_layout_p->grid_columns < view_layout_p->max_elements) {
906 	    view_layout_p->max_elements = view_layout_p->grid_rows * view_layout_p->grid_columns;
907 	}
908     } else  {// (iconview)
909 
910 
911 	view_layout_p->grid_columns = ((double)width / view_layout_p->cellwidth) + 0.5;
912 	view_layout_p->grid_rows = (view_layout_p->max_elements) / view_layout_p->grid_columns;
913 	if(view_layout_p->max_elements % view_layout_p->grid_columns)
914 	    view_layout_p->grid_rows++;
915 
916 	// Correct for number of rows in case the paper must also fill empty space.
917 
918 	gint items=(view_layout_p->cellwidth==0 || view_layout_p->cellheight==0)?-1:
919 		   view_layout_p->vpane_allocation.width *
920 		   view_layout_p->vpane_allocation.height /
921 		   view_layout_p->cellwidth/ view_layout_p->cellheight;
922 	NOOP(stderr, "init_grid (%d):items=%d pane allocation:w=%d h=%d \n",
923 		view_layout_p->max_elements, items,
924 		view_layout_p->vpane_allocation.width,
925 		view_layout_p->vpane_allocation.height);
926 	gint total_rows = items;
927 
928 	if (view_layout_p->grid_columns > 0) {
929 	    gint rows = total_rows / view_layout_p->grid_columns;
930 	    if (total_rows % view_layout_p->grid_columns != 0){
931 		// remainder...
932 		rows++;
933 	    }
934 	    total_rows = rows;
935 	} else total_rows = -1;
936 	if (view_layout_p->max_elements <= items - view_layout_p->grid_columns) {
937 	    // hacky correction for when population does not fill paper completely
938 	    total_rows = -1;
939 	}
940 
941 	if (total_rows > 0 && total_rows > view_layout_p->grid_rows) {
942 	    view_layout_p->grid_rows = total_rows;
943 	    NOOP( "changing rows to %d (items = %d)\n", total_rows, items);
944 	}
945     }
946     NOOP (stderr, "layout_reset_columns: rfm_allocation.width=%d rfm_allocation.height=%d\n",rfm_allocation.width,rfm_allocation.height);
947     NOOP (stderr, "layout_reset_columns: view_layout_p->max_elements=%d cellwidth=%d cellheight=%d\n",
948 	    view_layout_p->max_elements, view_layout_p->cellwidth, view_layout_p->cellheight);
949     NOOP (stderr, "layout_reset_columns: columns=%d rows=%d\n",
950 	    view_layout_p->grid_columns, view_layout_p->grid_rows);
951    view_layout_p->grid_area = view_layout_p->grid_rows * view_layout_p->grid_columns;
952 }
953 
954 static void
layout_configure(view_t * view_p,gint pathc)955 layout_configure(view_t *view_p, gint pathc){
956    if (!view_p) g_error("layout_configure: !view_p\n");
957     rfm_global_t *rfm_global_p = rfm_global();
958     if(!rfm_global_p) g_error ("layout_configure: rfm_global_p==NULL\n");
959     if(!rfm_global_p->window) g_error ("layout_configure: rfm_global_p->window==NULL\n");
960 
961     if (pathc == 0){
962 	DBG("init_grid: pathc==0, skipping...\n");
963 	return;
964     }
965     if(!rfm_global_p->window) g_error ("layout_configure: rfm_global_p->window==NULL\n");
966     view_layout_t *view_layout_p = &(view_p->view_layout);
967 
968     if (!(view_layout_p->tripwire & LAYOUT_ICON_SIZE))
969 	g_error("view_layout_p item LAYOUT_ICON_SIZE is not set\n");
970     GtkWidget *vpane = g_object_get_data(G_OBJECT(view_p->widgets.paper), "vpane");
971     if (vpane && !(view_layout_p->tripwire & LAYOUT_VPANE_ALLOCATION))
972 	g_error("view_layout_p item LAYOUT_VPANE_ALLOCATION is not set\n");
973 
974     NOOP(stderr, "layout_configure(): pathc=%d\n", pathc);
975     view_layout_p->max_elements = pathc;
976     layout_reset_columns(view_p);
977 
978      if (view_layout_p->icon_size < TINY_ICON_SIZE){
979         view_layout_p->paperX = 192; // hack : 192 is maximum cellwidth
980 	//view_layout_p->name_width + view_layout_p->details_width;
981     } else
982     {
983         view_layout_p->paperX = view_layout_p->cellwidth;
984     }
985 
986     view_layout_p->paperY = view_layout_p->grid_rows *  view_layout_p->cellheight;
987     view_layout_p->tripwire |= LAYOUT_ROOT_CONFIGURED;
988     rfm_layout_set_window_size(view_p, rfm_allocation.width, rfm_allocation.height);
989 
990     return;
991 }
992 
rfm_layout_set_window_size(view_t * view_p,gint width,gint height)993 gboolean rfm_layout_set_window_size(view_t *view_p, gint width, gint height){
994     if (!view_p) g_error("rfm_layout_set_window_size: !view_p\n");
995     view_layout_t *view_layout_p = &(view_p->view_layout);
996     if (width == view_layout_p->window_width && height == view_layout_p->window_height){
997 	return FALSE;
998     }
999     view_layout_p->window_width = width;
1000     view_layout_p->window_height = height;
1001     return TRUE;
1002 }
1003 
1004 void
rfm_layout_configure(view_t * view_p,gint pathc)1005 rfm_layout_configure(view_t *view_p, gint pathc){
1006     NOOP(stderr, "+++rfm_layout_configure\n");
1007     // (configure view layout)
1008     layout_configure(view_p, pathc);
1009 
1010     // check paper size
1011     view_layout_t *view_layout_p = &(view_p->view_layout);
1012 #if 10
1013     gboolean setup_not_ok =
1014 	!view_layout_p->paperX || !view_layout_p->paperY ||
1015 	view_layout_p->paperX !=
1016 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(view_p->widgets.paper), "paperX"))
1017 	||
1018 	view_layout_p->paperY !=
1019 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(view_p->widgets.paper), "paperY"));
1020 #else
1021     // This does not work (at present).
1022     // Does not present too much advantages either, memorywise.
1023     gboolean setup_not_ok =
1024 	!view_layout_p->paperX || !view_layout_p->paperY ||
1025 	view_layout_p->paperX <
1026 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(view_p->widgets.paper), "paperX"))
1027 	||
1028 	view_layout_p->paperY <
1029 	GPOINTER_TO_INT(g_object_get_data(G_OBJECT(view_p->widgets.paper), "paperY"));
1030 
1031 #endif
1032 
1033     if (setup_not_ok){
1034 
1035 	//static gint c=1;NOOP(stderr, "rfm_layout_configure(): reset paper size (%d)...\n)",c);
1036 
1037 	// set paper size
1038 	g_object_set_data(G_OBJECT(view_p->widgets.paper), "paper_setup", NULL);
1039 	rfm_context_function(set_paper_size, view_p);
1040 	rfm_context_function(context_sync, NULL);
1041 
1042 
1043 	// now that we have sync'd, activate reload on size changes.
1044 	g_object_set_data(G_OBJECT(view_p->widgets.paper), "paper_setup", GINT_TO_POINTER(1));
1045 	GtkWidget *size_scale = g_object_get_data(G_OBJECT(view_p->widgets.paper), "size_scale");
1046 	if (size_scale != NULL){
1047 	    // Disable reload by scale change signal,
1048 	    g_object_set_data(G_OBJECT(view_p->widgets.paper), "size_scale_disabled", GINT_TO_POINTER(1));
1049 	    rfm_context_function(rfm_layout_set_icon_size_scale, view_p);
1050 	    // sync
1051 	    rfm_context_function(context_sync, NULL);
1052 	    // and now reactivate reload by scale change signal.
1053 	    g_object_set_data(G_OBJECT(view_p->widgets.paper), "size_scale_disabled", NULL);
1054 	}
1055     }
1056 }
1057 
1058 
1059 ////////////////////////////////////////////////////////////////////////////////////////////
1060 
1061 gboolean
rfm_get_population_rect(view_t * view_p,const population_t * population_p,GdkRectangle * rect)1062 rfm_get_population_rect(view_t * view_p, const population_t * population_p, GdkRectangle *rect){
1063     view_layout_t *view_layout_p = &(view_p->view_layout);
1064     if (!(view_layout_p->tripwire & LAYOUT_CELLWIDTH))
1065 	g_error("view_layout_p item LAYOUT_CELLWIDTH is not set\n");
1066     if (!(view_layout_p->tripwire & LAYOUT_CELLHEIGHT))
1067 	g_error("view_layout_p item LAYOUT_CELLHEIGHT is not set\n");
1068 
1069     if (!population_p || !rect) {
1070 	DBG("rfm_get_population_rect() called with !population_p || !rect\n");
1071 	return FALSE;
1072     }
1073     if (!rfm_population_try_read_lock(view_p, "rfm_get_population_rect")) return FALSE;
1074     gint cellwidth = view_layout_p->cellwidth;
1075     gint cellheight = view_layout_p->cellheight;
1076     rect->x = population_p->column * cellwidth + MARGIN_LEFT(view_p);
1077     rect->y = population_p->row * cellheight + MARGIN_TOP(view_p);
1078     rect->width = cellwidth;
1079     rect->height = cellheight;
1080 
1081     rfm_population_read_unlock(view_p, "rfm_get_population_rect");
1082     return TRUE;
1083 }
1084 
1085 gboolean
rfm_get_population_icon_rect(view_t * view_p,const population_t * population_p,GdkRectangle * rect)1086 rfm_get_population_icon_rect(view_t * view_p, const population_t * population_p, GdkRectangle *rect){
1087     view_layout_t *view_layout_p = &(view_p->view_layout);
1088     if (!(view_layout_p->tripwire & LAYOUT_CELLWIDTH))
1089 	g_error("view_layout_p item LAYOUT_CELLWIDTH is not set\n");
1090     if (!(view_layout_p->tripwire & LAYOUT_CELLHEIGHT))
1091 	g_error("view_layout_p item LAYOUT_CELLHEIGHT is not set\n");
1092     gint cellwidth = view_layout_p->cellwidth;
1093     gint cellheight = view_layout_p->cellheight;
1094     if (!rfm_population_try_read_lock(view_p, "rfm_get_population_icon_rect")) {
1095 	DBG("rfm_get_population_icon_rect(): failed to get read lock\n");
1096 	return FALSE;
1097     }
1098     rect->x = population_p->column * cellwidth + MARGIN_LEFT(view_p);
1099     rect->y = population_p->row * cellheight + MARGIN_TOP(view_p);
1100 
1101 
1102     gint icon_size = view_layout_p->icon_size;
1103     if (!icon_size) icon_size = TINY_ICON_SIZE;
1104     rect->width =  icon_size;
1105     rect->height = icon_size;
1106 
1107     rfm_population_read_unlock(view_p, "rfm_get_population_icon_rect");
1108     return TRUE;
1109 }
1110 
1111 gboolean
rfm_get_population_label_rect(view_t * view_p,const population_t * population_p,GdkRectangle * rect)1112 rfm_get_population_label_rect(view_t * view_p, const population_t * population_p, GdkRectangle *rect){
1113     view_layout_t *view_layout_p = &(view_p->view_layout);
1114     if (!(view_layout_p->tripwire & LAYOUT_CELLWIDTH))
1115 	g_error("view_layout_p item LAYOUT_CELLWIDTH is not set\n");
1116     if (!(view_layout_p->tripwire & LAYOUT_CELLHEIGHT))
1117 	g_error("view_layout_p item LAYOUT_CELLHEIGHT is not set\n");
1118     gint cellwidth = view_layout_p->cellwidth;
1119     gint cellheight = view_layout_p->cellheight;
1120     if (!rfm_population_try_read_lock(view_p, "rfm_get_population_label_rect")) {
1121 	DBG("rfm_get_population_label_rect(): failed to get read lock\n");
1122 	return FALSE;
1123     }
1124     rect->x = population_p->column * cellwidth + MARGIN_LEFT(view_p);
1125     rect->y = population_p->row * cellheight + MARGIN_TOP(view_p);
1126 
1127     rect->height=0;
1128     rect->width=0;
1129     if(population_p->layout) {
1130 	rect->height = population_p->logical_rect.height;
1131 	rect->width = population_p->logical_rect.width;
1132     }
1133     gint x_offset = (view_layout_p->icon_size >= SMALL_ICON_SIZE)?
1134 	(cellwidth - population_p->logical_rect.width) / 2:
1135 	 TINY_ICON_SIZE + 2;
1136     // Details icon_size (0) does not have a layout2.
1137     if (view_layout_p->icon_size && population_p->layout2) {
1138 	rect->height += population_p->logical_rect2.height;
1139 	if (population_p->logical_rect2.width > population_p->logical_rect.width){
1140 	    rect->width = population_p->logical_rect2.width;
1141 	}
1142 	gint x_offset2 = (view_layout_p->icon_size >= SMALL_ICON_SIZE)?
1143 		(cellwidth - population_p->logical_rect2.width) / 2:
1144 		TINY_ICON_SIZE + 2;
1145 
1146 	if (x_offset2 < x_offset) {
1147 	    x_offset = x_offset2;
1148 	}
1149     }
1150 
1151     if (rect->x + x_offset<0) x_offset=0;
1152     else  rect->x += x_offset;
1153     if (view_layout_p->icon_size >= SMALL_ICON_SIZE) {
1154 	rect->y += (TEXTSPACING + ICON_SIZE(view_p));
1155     } else {
1156 	rect->y += TEXTSPACING;
1157     }
1158 
1159     rfm_population_read_unlock(view_p, "rfm_get_population_label_rect");
1160 
1161         // test code
1162     //if (population_p->flags & LABEL_SATURATED){
1163 	//rect->x -= rect->width; if (rect->x < 0) rect->x = 0;
1164 	//rect->width *= 2; rect->width +=2;
1165     //}
1166 
1167     return TRUE;
1168 }
1169 
1170 gboolean
rfm_get_population_label_rect_full(view_t * view_p,const population_t * population_p,GdkRectangle * rect)1171 rfm_get_population_label_rect_full(view_t * view_p, const population_t * population_p, GdkRectangle *rect){
1172     if (!view_p || ! population_p) {
1173 	    g_error("incorrect function call: layout_full_dimensions()");
1174     }
1175     if (!rfm_population_try_read_lock(view_p, "rfm_get_population_label_rect_full")) {
1176 	DBG("rfm_get_population_label_rect(): failed to get read lock\n");
1177 	return FALSE;
1178     }
1179 
1180     GdkRectangle item_rect;
1181     GdkRectangle label_rect;
1182     if (!rfm_get_population_label_rect(view_p, population_p, &label_rect)) {
1183 	DBG("rfm_get_population_label_rect_full: !rfm_get_population_label_rect\n");
1184 	return FALSE;
1185     }
1186     if (!rfm_get_population_rect(view_p, population_p, &item_rect)) {
1187 	DBG("rfm_get_population_label_rect_full: !rfm_get_population_rect\n");
1188 	return FALSE;
1189     }
1190     view_layout_t *view_layout_p = &(view_p->view_layout);
1191 
1192     rect->width = population_p->logical_rect_full.width;
1193     rect->height = population_p->logical_rect_full.height;
1194     rect->y = label_rect.y;
1195 
1196     // with texts under the icons, center the saturated text.
1197     if (view_layout_p->icon_size >= SMALL_ICON_SIZE) {
1198 	gint center = item_rect.x + (item_rect.width/2);
1199 	rect->x = center - (rect->width/2);
1200 	// bigger bg square for non details...
1201 	rect->width += 4;
1202 	rect->height += 4;
1203 	rect->y += 2;
1204 
1205     } else {
1206 	// texts to the right of the icon, use label.x
1207 	rect->x = label_rect.x;
1208     }
1209 
1210     // correct for overlap
1211     gint scrollbar_width = 25;
1212     gint area_width;
1213     GtkWidget *vpane = g_object_get_data(G_OBJECT(view_p->widgets.paper), "vpane");
1214     if (vpane) {
1215 	area_width = view_layout_p->vpane_allocation.width;
1216     } else {
1217 	area_width = rfm_allocation.width;
1218     }
1219 
1220     NOOP(stderr, "overlap: x=%d, w=%d (%d), aw=%d nx=%d\n",rect->x,rect->width,rect->x+rect->width,area_width,area_width - rect->width);
1221 
1222     if (rect->x + rect->width + scrollbar_width >= area_width) {
1223 	rect->x = area_width - rect->width - scrollbar_width;
1224     }
1225     // correct for underlap
1226     if (rect->x < MARGIN_LEFT(view_p)) rect->x = MARGIN_LEFT(view_p);
1227     rfm_population_read_unlock(view_p, "rfm_get_population_label_rect_full");
1228     return TRUE;
1229 }
1230 ////////////////////////////////////////////////////////////////////////////////////////////
1231 
1232