1 // This code is adapted from 'imageviewer', a demo image viewer found
2 // in the FOX library and written by Jeroen van der Zijp.
3
4 #include "config.h"
5 #include "i18n.h"
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10 #include <sys/wait.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <signal.h>
14
15 #include <fx.h>
16 #include <fxkeys.h>
17 #include <FXPNGImage.h>
18 #include <FXJPGImage.h>
19 #include <FXTIFImage.h>
20 #include <FXPNGIcon.h>
21
22 #include "xfedefs.h"
23 #include "icons.h"
24 #include "xfeutils.h"
25 #include "startupnotification.h"
26 #include "FileDialog.h"
27 #include "InputDialog.h"
28 #include "DirHistBox.h"
29 #include "MessageBox.h"
30 #include "FileList.h"
31 #include "XFileImage.h"
32
33 // Add FOX hacks
34 #include "foxhacks.cpp"
35 #include "clearlooks.cpp"
36
37 // Global variables
38 char** args;
39 FXColor listbackcolor, listforecolor;
40 FXColor highlightcolor;
41 FXbool allowPopupScroll = false;
42 FXuint single_click;
43 FXbool file_tooltips;
44 FXbool relative_resize;
45 FXbool show_pathlink;
46 FXbool save_win_pos;
47 FXString homedir;
48 FXString xdgconfighome;
49 FXString xdgdatahome;
50 FXbool xim_used = false;
51
52 // Main window (not used but necessary for compilation)
53 FXMainWindow* mainWindow = NULL;
54
55 // Scaling factors for the UI
56 extern double scalefrac;
57
58 // Hand cursor replacement (integer scaling factor = 1)
59 #define hand1_width 32
60 #define hand1_height 32
61 #define hand1_x_hot 6
62 #define hand1_y_hot 1
63 static const FXuchar hand1_bits[] =
64 {
65 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
66 0x90, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00,
67 0x90, 0x1c, 0x00, 0x00, 0x10, 0xe4, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
68 0x12, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x92, 0x24, 0x01, 0x00,
69 0x82, 0x24, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
70 0x02, 0x00, 0x01, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
76 };
77
78 static const FXuchar hand1_mask_bits[] =
79 {
80 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
81 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00,
82 0xf0, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00,
83 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0x01, 0x00,
84 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0x01, 0x00,
85 0xfe, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
91 };
92
93
94 // Hand cursor replacement (integer scaling factor = 2)
95 #define hand2_width 32
96 #define hand2_height 32
97 #define hand2_x_hot 6
98 #define hand2_y_hot 1
99 static const FXuchar hand2_bits[] =
100 {
101 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
102 0x60, 0x06, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
103 0x20, 0x1e, 0x00, 0x00, 0x60, 0x3e, 0x00, 0x00, 0x20, 0xe2, 0x03, 0x00,
104 0x60, 0x62, 0x1e, 0x00, 0x38, 0x00, 0x74, 0x00, 0x7c, 0x00, 0x60, 0x00,
105 0x24, 0x00, 0x40, 0x00, 0x64, 0x00, 0x60, 0x00, 0x26, 0x00, 0x40, 0x00,
106 0x26, 0x22, 0x62, 0x00, 0x06, 0x22, 0x42, 0x00, 0x06, 0x00, 0x60, 0x00,
107 0x06, 0x00, 0x40, 0x00, 0x06, 0x00, 0x60, 0x00, 0x04, 0x00, 0x60, 0x00,
108 0xfc, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
112 };
113
114 static const FXuchar hand2_mask_bits[] =
115 {
116 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00,
117 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00,
118 0xe0, 0x1f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0x03, 0x00,
119 0xe0, 0xff, 0x1f, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x7f, 0x00,
120 0xfc, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x7f, 0x00,
121 0xfe, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x7f, 0x00,
122 0xfe, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x7f, 0x00,
123 0xfc, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
127 };
128
129
130 // Hand cursor replacement (integer scaling factor = 3 or more)
131 #define hand3_width 32
132 #define hand3_height 32
133 #define hand3_x_hot 6
134 #define hand3_y_hot 1
135 static const FXuchar hand3_bits[] =
136 {
137 0x80, 0x1f, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0x30, 0x00, 0x00,
138 0xc0, 0x30, 0x00, 0x00, 0xc0, 0x30, 0x00, 0x00, 0xc0, 0x30, 0x00, 0x00,
139 0xc0, 0x30, 0x00, 0x00, 0xc0, 0x30, 0x00, 0x00, 0xc0, 0xf0, 0x03, 0x00,
140 0xc0, 0xf0, 0x07, 0x00, 0xc0, 0x30, 0xfe, 0x00, 0xc0, 0x10, 0xfe, 0x01,
141 0xc0, 0x10, 0x8c, 0x3f, 0xc0, 0x10, 0x04, 0x7f, 0xfc, 0x00, 0x04, 0xe1,
142 0xfe, 0x00, 0x04, 0xc1, 0xc6, 0x00, 0x04, 0xc0, 0xc6, 0x00, 0x00, 0xc0,
143 0xc6, 0x00, 0x00, 0xc0, 0xc3, 0x00, 0x00, 0xc0, 0xc3, 0x00, 0x00, 0xc0,
144 0xc3, 0x10, 0x04, 0xc1, 0x03, 0x10, 0x04, 0xc1, 0x03, 0x10, 0x04, 0xc1,
145 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
146 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0,
147 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f
148 };
149
150 static const FXuchar hand3_mask_bits[] =
151 {
152 0x80, 0x1f, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00,
153 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00,
154 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00,
155 0xc0, 0xff, 0x07, 0x00, 0xc0, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x01,
156 0xc0, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff,
157 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
158 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
161 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
162 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f
163 };
164
165
166 // Predefined zoom factors
167 #define NB_ZOOM 24
168 double zoomtab[NB_ZOOM] =
169 {
170 0.01, 0.025, 0.05, 0.075, 0.10, 0.15, 0.20, 0.30, 0.50, 0.75, 1, \
171 1.5, 2, 3, 4, 5, 7.5, 10, 15, 20, 30, 50, 75, 100
172 };
173 #define ZOOM_100 10
174
175 // Maximum image size (in pixels) for zooming in
176 #define MAX_IMGSIZE 5120
177
178 // Patterns for supported image formats
179 const char* patterns[] =
180 {
181 _("All Files"), "*",
182 _("GIF Image"), "*.gif",
183 _("BMP Image"), "*.bmp",
184 _("XPM Image"), "*.xpm",
185 _("PCX Image"), "*.pcx",
186 _("ICO Image"), "*.ico",
187 _("RGB Image"), "*.rgb",
188 _("XBM Image"), "*.xbm",
189 _("TARGA Image"), "*.tga",
190 _("PPM Image"), "*.ppm",
191 _("PNG Image"), "*.png",
192 _("JPEG Image"), "*.jpg",
193 _("JPEG Image"), "*.jpeg",
194 _("TIFF Image"), "*.tif",
195 _("TIFF Image"), "*.tiff",
196 NULL
197 };
198
199
200 const FXString imgpatterns = "*.gif,*.bmp,*.xpm,*.pcx,*.ico,*.rgb,*.xbm,*.tga,*.ppm,*.png,*.jpg,*.jpeg,*.tif,*.tiff";
201
202
203 // Helper function to draw a toolbar separator
toolbarSeparator(FXToolBar * tb)204 void toolbarSeparator(FXToolBar* tb)
205 {
206 #define SEP_SPACE_TB 1
207 new FXFrame(tb, LAYOUT_CENTER_Y|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, SEP_SPACE_TB);
208 new FXVerticalSeparator(tb, LAYOUT_SIDE_TOP|LAYOUT_CENTER_Y|SEPARATOR_GROOVE|LAYOUT_FILL_Y);
209 new FXFrame(tb, LAYOUT_CENTER_Y|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, SEP_SPACE_TB);
210 }
211
212
213 // Helper function to draw a separator in an horizontal frame
hframeSeparator(FXHorizontalFrame * hframe)214 void hframeSeparator(FXHorizontalFrame* hframe)
215 {
216 #define SEP_SPACE_HF 5
217 new FXFrame(hframe, LAYOUT_CENTER_Y|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, SEP_SPACE_HF);
218 new FXVerticalSeparator(hframe, LAYOUT_SIDE_TOP|LAYOUT_CENTER_Y|SEPARATOR_GROOVE|LAYOUT_FILL_Y);
219 new FXFrame(hframe, LAYOUT_CENTER_Y|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, SEP_SPACE_HF);
220 }
221
222
223 // Map
224 FXDEFMAP(XFileImage) XFileImageMap[] =
225 {
226 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ABOUT, XFileImage::onCmdAbout),
227 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_OPEN, XFileImage::onCmdOpen),
228 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_TITLE, XFileImage::onUpdTitle),
229 FXMAPFUNC(SEL_SIGNAL, XFileImage::ID_HARVEST, XFileImage::onSigHarvest),
230 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_QUIT, XFileImage::onCmdQuit),
231 FXMAPFUNC(SEL_SIGNAL, XFileImage::ID_QUIT, XFileImage::onCmdQuit),
232 FXMAPFUNC(SEL_CLOSE, XFileImage::ID_TITLE, XFileImage::onCmdQuit),
233 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_RESTART, XFileImage::onCmdRestart),
234 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_TOGGLE_FILELIST_BEFORE, XFileImage::onCmdToggleFileListBefore),
235 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_HORZ_PANELS, XFileImage::onCmdHorzVertPanels),
236 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_VERT_PANELS, XFileImage::onCmdHorzVertPanels),
237 FXMAPFUNC(SEL_DOUBLECLICKED, XFileImage::ID_FILELIST, XFileImage::onCmdItemDoubleClicked),
238 FXMAPFUNC(SEL_CLICKED, XFileImage::ID_FILELIST, XFileImage::onCmdItemClicked),
239 FXMAPFUNC(SEL_KEYPRESS, 0, XFileImage::onKeyPress),
240 FXMAPFUNC(SEL_KEYRELEASE, 0, XFileImage::onKeyRelease),
241 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_RECENTFILE, XFileImage::onCmdRecentFile),
242 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_TOGGLE_HIDDEN, XFileImage::onCmdToggleHidden),
243 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_TOGGLE_THUMBNAILS, XFileImage::onCmdToggleThumbnails),
244 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_SHOW_DETAILS, XFileImage::onCmdShowDetails),
245 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_SHOW_MINI_ICONS, XFileImage::onCmdShowMini),
246 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_SHOW_BIG_ICONS, XFileImage::onCmdShowBig),
247 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ROTATE_90, XFileImage::onCmdRotate),
248 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ROTATE_270, XFileImage::onCmdRotate),
249 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_MIRROR_HOR, XFileImage::onCmdMirror),
250 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_MIRROR_VER, XFileImage::onCmdMirror),
251 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ZOOM_IN, XFileImage::onCmdZoomIn),
252 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ZOOM_OUT, XFileImage::onCmdZoomOut),
253 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ZOOM_100, XFileImage::onCmdZoom100),
254 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_ZOOM_WIN, XFileImage::onCmdZoomWin),
255 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_PRINT, XFileImage::onCmdPrint),
256 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_DIR_UP, XFileImage::onCmdDirUp),
257 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_DIR_UP, XFileImage::onUpdDirUp),
258 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_DIR_BACK, XFileImage::onCmdDirBack),
259 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_DIR_BACK, XFileImage::onUpdDirBack),
260 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_DIR_FORWARD, XFileImage::onCmdDirForward),
261 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_DIR_FORWARD, XFileImage::onUpdDirForward),
262 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_DIR_BACK_HIST, XFileImage::onCmdDirBackHist),
263 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_DIR_BACK_HIST, XFileImage::onUpdDirBackHist),
264 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_DIR_FORWARD_HIST, XFileImage::onCmdDirForwardHist),
265 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_DIR_FORWARD_HIST, XFileImage::onUpdDirForwardHist),
266 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_GO_HOME, XFileImage::onCmdHome),
267 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_PRINT, XFileImage::onUpdImage),
268 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_ROTATE_90, XFileImage::onUpdImage),
269 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_ROTATE_270, XFileImage::onUpdImage),
270 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_MIRROR_HOR, XFileImage::onUpdImage),
271 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_MIRROR_VER, XFileImage::onUpdImage),
272 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_ZOOM_IN, XFileImage::onUpdImage),
273 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_ZOOM_OUT, XFileImage::onUpdImage),
274 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_ZOOM_100, XFileImage::onUpdImage),
275 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_ZOOM_WIN, XFileImage::onUpdImage),
276 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_SHOW_BIG_ICONS, XFileImage::onUpdFileView),
277 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_SHOW_MINI_ICONS, XFileImage::onUpdFileView),
278 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_SHOW_DETAILS, XFileImage::onUpdFileView),
279 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_TOGGLE_HIDDEN, XFileImage::onUpdToggleHidden),
280 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_TOGGLE_FILELIST_BEFORE, XFileImage::onUpdToggleFileListBefore),
281 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_TOGGLE_THUMBNAILS, XFileImage::onUpdToggleThumbnails),
282 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_TOGGLE_FIT_WIN, XFileImage::onCmdToggleFitWin),
283 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_TOGGLE_FILTER_IMAGES, XFileImage::onCmdToggleFilterImages),
284 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_TOGGLE_FIT_WIN, XFileImage::onUpdToggleFitWin),
285 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_TOGGLE_FILTER_IMAGES, XFileImage::onUpdToggleFilterImages),
286 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_HORZ_PANELS, XFileImage::onUpdHorzVertPanels),
287 FXMAPFUNC(SEL_UPDATE, XFileImage::ID_VERT_PANELS, XFileImage::onUpdHorzVertPanels),
288 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_GO_HOME, XFileImage::onCmdHome),
289 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_GO_WORK, XFileImage::onCmdWork),
290 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, XFileImage::ID_FILELIST, XFileImage::onCmdPopupMenu),
291 FXMAPFUNC(SEL_COMMAND, XFileImage::ID_POPUP_MENU, XFileImage::onCmdPopupMenu),
292 };
293
294
295 // Object implementation
FXIMPLEMENT(XFileImage,FXMainWindow,XFileImageMap,ARRAYNUMBER (XFileImageMap))296 FXIMPLEMENT(XFileImage, FXMainWindow, XFileImageMap, ARRAYNUMBER(XFileImageMap))
297
298
299 // Make some windows
300 XFileImage::XFileImage(FXApp* a, FXbool smoothscroll) : FXMainWindow(a, "Xfi ", NULL, NULL, DECOR_ALL)
301 {
302 setIcon(xfiicon);
303
304 FXButton* btn = NULL;
305 FXHotKey hotkey;
306 FXString key;
307
308 setTarget(this);
309 setSelector(ID_TITLE);
310
311 // Make menu bar
312 menubar = new FXMenuBar(this, LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED);
313
314 // Sites where to dock
315 FXDockSite* topdock = new FXDockSite(this, LAYOUT_SIDE_TOP|LAYOUT_FILL_X);
316 new FXDockSite(this, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
317 new FXDockSite(this, LAYOUT_SIDE_LEFT|LAYOUT_FILL_Y);
318 new FXDockSite(this, LAYOUT_SIDE_RIGHT|LAYOUT_FILL_Y);
319
320 // Tool bar
321 FXToolBarShell* dragshell1 = new FXToolBarShell(this, FRAME_RAISED);
322 toolbar = new FXToolBar(topdock, dragshell1, LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED);
323 new FXToolBarGrip(toolbar, toolbar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
324
325 // File menu
326 filemenu = new FXMenuPane(this);
327 new FXMenuTitle(menubar, _("&File"), NULL, filemenu);
328
329 // Image Menu
330 imagemenu = new FXMenuPane(this);
331 new FXMenuTitle(menubar, _("&Image"), NULL, imagemenu);
332
333 // View menu
334 viewmenu = new FXMenuPane(this);
335 new FXMenuTitle(menubar, _("&View"), NULL, viewmenu);
336
337 // Preferences Menu
338 prefsmenu = new FXMenuPane(this);
339 new FXMenuTitle(menubar, _("&Preferences"), NULL, prefsmenu);
340
341 // Help menu
342 helpmenu = new FXMenuPane(this);
343 new FXMenuTitle(menubar, _("&Help"), NULL, helpmenu);
344
345 // Splitter
346 FXVerticalFrame* vframe = new FXVerticalFrame(this, LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
347
348 // Set order of the file list and image widgets
349 filelistbefore = getApp()->reg().readUnsignedEntry("OPTIONS", "filelist_before", false);
350 if (filelistbefore)
351 {
352 splitter = new FXSplitter(vframe, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_TRACKING|SPLITTER_VERTICAL);
353 filebox = new FXVerticalFrame(splitter, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
354 imageview = new FXImageView(splitter, NULL, NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN);
355 }
356 else
357 {
358 splitter = new FXSplitter(vframe, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_TRACKING|SPLITTER_VERTICAL|SPLITTER_REVERSED);
359 imageview = new FXImageView(splitter, NULL, NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN);
360 filebox = new FXVerticalFrame(splitter, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
361 }
362
363 // Stack panels horizontally or vertically
364 vertpanels = getApp()->reg().readUnsignedEntry("OPTIONS", "vert_panels", false);
365 if (vertpanels)
366 {
367 splitter->setSplitterStyle(splitter->getSplitterStyle()&~SPLITTER_VERTICAL);
368 }
369 else
370 {
371 splitter->setSplitterStyle(splitter->getSplitterStyle()|SPLITTER_VERTICAL);
372 }
373
374 // Container for the action buttons
375 FXHorizontalFrame* buttons = new FXHorizontalFrame(filebox, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0);
376
377 // Container for the path linker
378 FXHorizontalFrame* pathframe = new FXHorizontalFrame(filebox, LAYOUT_FILL_X|FRAME_RAISED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
379
380 // File list
381 FXuint options;
382 if (smoothscroll)
383 {
384 options = LAYOUT_FILL_X|LAYOUT_FILL_Y|_ICONLIST_MINI_ICONS|_ICONLIST_BROWSESELECT;
385 }
386 else
387 {
388 options = LAYOUT_FILL_X|LAYOUT_FILL_Y|_ICONLIST_MINI_ICONS|_ICONLIST_BROWSESELECT|SCROLLERS_DONT_TRACK;
389 }
390
391 thumbnails = getApp()->reg().readUnsignedEntry("OPTIONS", "thumbnails", 0);
392 filelist = new FileList(this, filebox, this, ID_FILELIST, thumbnails, options);
393 filelist->setTextColor(listforecolor);
394 filelist->setBackColor(listbackcolor);
395 filelist->setHeaderSize(0, getApp()->reg().readUnsignedEntry("OPTIONS", "name_size", 200));
396 filelist->setHeaderSize(1, getApp()->reg().readUnsignedEntry("OPTIONS", "size_size", 60));
397 filelist->setHeaderSize(2, getApp()->reg().readUnsignedEntry("OPTIONS", "type_size", 100));
398 filelist->setHeaderSize(3, getApp()->reg().readUnsignedEntry("OPTIONS", "ext_size", 100));
399 filelist->setHeaderSize(4, getApp()->reg().readUnsignedEntry("OPTIONS", "modd_size", 150));
400 filelist->setHeaderSize(5, getApp()->reg().readUnsignedEntry("OPTIONS", "user_size", 50));
401 filelist->setHeaderSize(6, getApp()->reg().readUnsignedEntry("OPTIONS", "grou_size", 50));
402 filelist->setHeaderSize(7, getApp()->reg().readUnsignedEntry("OPTIONS", "attr_size", 100));
403
404 // Action buttons
405 new FXFrame(buttons, LAYOUT_FIX_WIDTH, 0, 0, 4, 1);
406
407 key = getApp()->reg().readStringEntry("KEYBINDINGS", "go_back", "Ctrl-Backspace");
408 btn = new FXButton(buttons, TAB+_("Go to previous folder")+PARS(key), dirbackicon, this, ID_DIR_BACK, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
409 hotkey = _parseAccel(key);
410 btn->addHotKey(hotkey);
411 btnbackhist = new FXArrowButton(buttons, this, ID_DIR_BACK_HIST, LAYOUT_FILL_Y|FRAME_RAISED|FRAME_THICK|ARROW_DOWN|ARROW_TOOLBAR);
412
413 key = getApp()->reg().readStringEntry("KEYBINDINGS", "go_forward", "Shift-Backspace");
414 btn = new FXButton(buttons, TAB+_("Go to next folder")+PARS(key), dirforwardicon, this, ID_DIR_FORWARD, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
415 hotkey = _parseAccel(key);
416 btn->addHotKey(hotkey);
417 btnforwardhist = new FXArrowButton(buttons, this, ID_DIR_FORWARD_HIST, LAYOUT_FILL_Y|FRAME_RAISED|FRAME_THICK|ARROW_DOWN|ARROW_TOOLBAR);
418
419 key = getApp()->reg().readStringEntry("KEYBINDINGS", "go_up", "Backspace");
420 btn = new FXButton(buttons, TAB+_("Go to parent folder")+PARS(key), dirupicon, this, ID_DIR_UP, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
421 hotkey = _parseAccel(key);
422 btn->addHotKey(hotkey);
423
424 // Separator
425 hframeSeparator(buttons);
426
427 key = getApp()->reg().readStringEntry("KEYBINDINGS", "go_home", "Ctrl-H");
428 new FXButton(buttons, TAB+_("Go to home folder")+PARS(key), homeicon, this, ID_GO_HOME, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
429 hotkey = _parseAccel(key);
430 btn->addHotKey(hotkey);
431
432 key = getApp()->reg().readStringEntry("KEYBINDINGS", "go_work", "Shift-F2");
433 new FXButton(buttons, TAB+_("Go to working folder")+PARS(key), workicon, this, ID_GO_WORK, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
434 hotkey = _parseAccel(key);
435 btn->addHotKey(hotkey);
436
437 // Separator
438 hframeSeparator(buttons);
439
440 // Switch display modes
441 key = getApp()->reg().readStringEntry("KEYBINDINGS", "big_icons", "F10");
442 btn = new FXButton(buttons, TAB+_("Big icon list")+PARS(key), bigiconsicon, this, ID_SHOW_BIG_ICONS, BUTTON_TOOLBAR|LAYOUT_CENTER_Y|LAYOUT_LEFT|ICON_BEFORE_TEXT|FRAME_RAISED);
443 hotkey = _parseAccel(key);
444 btn->addHotKey(hotkey);
445
446 key = getApp()->reg().readStringEntry("KEYBINDINGS", "small_icons", "F11");
447 btn = new FXButton(buttons, TAB+_("Small icon list")+PARS(key), smalliconsicon, this, ID_SHOW_MINI_ICONS, BUTTON_TOOLBAR|LAYOUT_CENTER_Y|LAYOUT_LEFT|ICON_BEFORE_TEXT|FRAME_RAISED);
448 hotkey = _parseAccel(key);
449 btn->addHotKey(hotkey);
450
451 key = getApp()->reg().readStringEntry("KEYBINDINGS", "detailed_file_list", "F12");
452 btn = new FXButton(buttons, TAB+_("Detailed file list")+PARS(key), detailsicon, this, ID_SHOW_DETAILS, BUTTON_TOOLBAR|LAYOUT_CENTER_Y|LAYOUT_LEFT|ICON_BEFORE_TEXT|FRAME_RAISED);
453 hotkey = _parseAccel(key);
454 btn->addHotKey(hotkey);
455
456 // Separator
457 hframeSeparator(buttons);
458
459 // Vertical panels
460 key = getApp()->reg().readStringEntry("KEYBINDINGS", "vert_panels", "Ctrl-Shift-F1");
461 btn = new FXButton(buttons, TAB+_("Vertical panels")+PARS(key), vertpanelsicon, this, XFileImage::ID_VERT_PANELS, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT|ICON_BEFORE_TEXT);
462 hotkey = _parseAccel(key);
463 btn->addHotKey(hotkey);
464
465 // Horizontal panels
466 key = getApp()->reg().readStringEntry("KEYBINDINGS", "horz_panels", "Ctrl-Shift-F2");
467 btn = new FXButton(buttons, TAB+_("Horizontal panels")+PARS(key), horzpanelsicon, this, XFileImage::ID_HORZ_PANELS, BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT|ICON_BEFORE_TEXT);
468 hotkey = _parseAccel(key);
469 btn->addHotKey(hotkey);
470
471 // Panel title
472 pathtext = new TextLabel(pathframe, 0, this, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y);
473 pathtext->setBackColor(getApp()->getBaseColor());
474
475 // Path linker
476 pathlink = new PathLinker(pathframe, filelist, NULL, LAYOUT_FILL_X);
477
478 // Status bar
479 statusbar = new FXHorizontalFrame(vframe, JUSTIFY_LEFT|LAYOUT_FILL_X|FRAME_RAISED, 0, 0, 0, 0, 3, 3, 0, 0);
480
481 // Read and set sort function for file list
482 FXString sort_func = getApp()->reg().readStringEntry("OPTIONS", "sort_func", "ascendingCase");
483 if (sort_func == "ascendingCase")
484 {
485 filelist->setSortFunc(filelist->ascendingCase);
486 }
487 if (sort_func == "ascendingCaseMix")
488 {
489 filelist->setSortFunc(filelist->ascendingCaseMix);
490 }
491 else if (sort_func == "descendingCase")
492 {
493 filelist->setSortFunc(filelist->descendingCase);
494 }
495 else if (sort_func == "descendingCaseMix")
496 {
497 filelist->setSortFunc(filelist->descendingCaseMix);
498 }
499 else if (sort_func == "ascending")
500 {
501 filelist->setSortFunc(filelist->ascending);
502 }
503 else if (sort_func == "ascendingMix")
504 {
505 filelist->setSortFunc(filelist->ascendingMix);
506 }
507 else if (sort_func == "descending")
508 {
509 filelist->setSortFunc(filelist->descending);
510 }
511 else if (sort_func == "descendingMix")
512 {
513 filelist->setSortFunc(filelist->descendingMix);
514 }
515 else if (sort_func == "ascendingSize")
516 {
517 filelist->setSortFunc(filelist->ascendingSize);
518 }
519 else if (sort_func == "ascendingSizeMix")
520 {
521 filelist->setSortFunc(filelist->ascendingSizeMix);
522 }
523 else if (sort_func == "descendingSize")
524 {
525 filelist->setSortFunc(filelist->descendingSize);
526 }
527 else if (sort_func == "descendingSizeMix")
528 {
529 filelist->setSortFunc(filelist->descendingSizeMix);
530 }
531 else if (sort_func == "ascendingType")
532 {
533 filelist->setSortFunc(filelist->ascendingType);
534 }
535 else if (sort_func == "ascendingTypeMix")
536 {
537 filelist->setSortFunc(filelist->ascendingTypeMix);
538 }
539 else if (sort_func == "descendingType")
540 {
541 filelist->setSortFunc(filelist->descendingType);
542 }
543 else if (sort_func == "descendingTypeMix")
544 {
545 filelist->setSortFunc(filelist->descendingTypeMix);
546 }
547 else if (sort_func == "ascendingExt")
548 {
549 filelist->setSortFunc(filelist->ascendingExt);
550 }
551 else if (sort_func == "ascendingExtMix")
552 {
553 filelist->setSortFunc(filelist->ascendingExtMix);
554 }
555 else if (sort_func == "descendingExt")
556 {
557 filelist->setSortFunc(filelist->descendingExt);
558 }
559 else if (sort_func == "descendingExtMix")
560 {
561 filelist->setSortFunc(filelist->descendingExtMix);
562 }
563 else if (sort_func == "ascendingTime")
564 {
565 filelist->setSortFunc(filelist->ascendingTime);
566 }
567 else if (sort_func == "ascendingTimeMix")
568 {
569 filelist->setSortFunc(filelist->ascendingTimeMix);
570 }
571 else if (sort_func == "descendingTime")
572 {
573 filelist->setSortFunc(filelist->descendingTime);
574 }
575 else if (sort_func == "descendingTimeMix")
576 {
577 filelist->setSortFunc(filelist->descendingTimeMix);
578 }
579 else if (sort_func == "ascendingUser")
580 {
581 filelist->setSortFunc(filelist->ascendingUser);
582 }
583 else if (sort_func == "ascendingUserMix")
584 {
585 filelist->setSortFunc(filelist->ascendingUserMix);
586 }
587 else if (sort_func == "descendingUser")
588 {
589 filelist->setSortFunc(filelist->descendingUser);
590 }
591 else if (sort_func == "descendingUserMix")
592 {
593 filelist->setSortFunc(filelist->descendingUserMix);
594 }
595 else if (sort_func == "ascendingGroup")
596 {
597 filelist->setSortFunc(filelist->ascendingGroup);
598 }
599 else if (sort_func == "ascendingGroupMix")
600 {
601 filelist->setSortFunc(filelist->ascendingGroupMix);
602 }
603 else if (sort_func == "descendingGroup")
604 {
605 filelist->setSortFunc(filelist->descendingGroup);
606 }
607 else if (sort_func == "descendingGroupMix")
608 {
609 filelist->setSortFunc(filelist->descendingGroupMix);
610 }
611 else if (sort_func == "ascendingPerm")
612 {
613 filelist->setSortFunc(filelist->ascendingPerm);
614 }
615 else if (sort_func == "ascendingPermMix")
616 {
617 filelist->setSortFunc(filelist->ascendingPermMix);
618 }
619 else if (sort_func == "descendingPerm")
620 {
621 filelist->setSortFunc(filelist->descendingPerm);
622 }
623 else if (sort_func == "descendingPermMix")
624 {
625 filelist->setSortFunc(filelist->descendingPermMix);
626 }
627
628 // Single click navigation
629 if (single_click == SINGLE_CLICK_DIR_FILE)
630 {
631 filelist->setDefaultCursor(getApp()->getDefaultCursor(DEF_HAND_CURSOR));
632 }
633
634 // Status bar buttons
635 key = getApp()->reg().readStringEntry("KEYBINDINGS", "hidden_files", "Ctrl-F6");
636 new FXToggleButton(statusbar, TAB+_("Show hidden files")+PARS(key), TAB+_("Hide hidden files")+PARS(key), showhiddenicon, hidehiddenicon, this->filelist,
637 FileList::ID_TOGGLE_HIDDEN, BUTTON_TOOLBAR|LAYOUT_LEFT|ICON_BEFORE_TEXT);
638
639 key = getApp()->reg().readStringEntry("KEYBINDINGS", "thumbnails", "Ctrl-F7");
640 new FXToggleButton(statusbar, TAB+_("Show thumbnails")+PARS(key), TAB+_("Hide thumbnails")+PARS(key), showthumbicon, hidethumbicon, this->filelist,
641 FileList::ID_TOGGLE_THUMBNAILS, BUTTON_TOOLBAR|LAYOUT_LEFT|ICON_BEFORE_TEXT);
642
643 new FXStatusBar(statusbar, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
644 new FXDragCorner(statusbar);
645
646 // Toolbar button: Open file
647 key = getApp()->reg().readStringEntry("KEYBINDINGS", "open", "Ctrl-O");
648 new FXButton(toolbar, TAB+_("Open")+PARS(key)+TAB+_("Open image file.")+PARS(key), fileopenicon, this, ID_OPEN, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
649
650 // Toolbar button: Print
651 key = getApp()->reg().readStringEntry("KEYBINDINGS", "print", "Ctrl-P");
652 new FXButton(toolbar, TAB+_("Print")+PARS(key)+TAB+_("Print image file.")+PARS(key), printicon, this, ID_PRINT, BUTTON_TOOLBAR|FRAME_RAISED);
653
654 // Separator
655 toolbarSeparator(toolbar);
656
657 // Note : Ctrl+ and Ctrl- cannot be changed from the registry!
658
659 // Toolbar button: Zoom in
660 btn = new FXButton(toolbar, TAB+_("Zoom in")+PARS("Ctrl+")+TAB+_("Zoom in image.")+PARS("Ctrl+"), zoominicon, this, ID_ZOOM_IN, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
661 hotkey = (CONTROLMASK<<16) | KEY_KP_Add;
662 btn->addHotKey(hotkey);
663
664 // Toolbar button: Zoom out
665 btn = new FXButton(toolbar, TAB+_("Zoom out")+PARS("Ctrl-")+TAB+_("Zoom out image.")+PARS("Ctrl-"), zoomouticon, this, ID_ZOOM_OUT, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
666 hotkey = (CONTROLMASK<<16) | KEY_KP_Subtract;
667 btn->addHotKey(hotkey);
668
669 // Toolbar button: Zoom 100%
670 key = getApp()->reg().readStringEntry("KEYBINDINGS", "zoom_100", "Ctrl-I");
671 new FXButton(toolbar, TAB+_("Zoom 100%")+PARS(key)+TAB+_("Zoom image to 100%.")+PARS(key), zoom100icon, this, ID_ZOOM_100, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
672
673 // Toolbar button: Zoom to fit window
674 key = getApp()->reg().readStringEntry("KEYBINDINGS", "zoom_win", "Ctrl-F");
675 new FXButton(toolbar, TAB+_("Zoom to fit")+PARS(key)+TAB+_("Zoom to fit window.")+PARS(key), zoomwinicon, this, ID_ZOOM_WIN, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
676
677 // Separator
678 toolbarSeparator(toolbar);
679
680 // Toolbar button: Rotate left
681 key = getApp()->reg().readStringEntry("KEYBINDINGS", "rotate_left", "Ctrl-L");
682 new FXButton(toolbar, TAB+_("Rotate left")+PARS(key)+TAB+_("Rotate left image.")+PARS(key), rotatelefticon, this, ID_ROTATE_90, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
683
684 // Toolbar button: Rotate right
685 key = getApp()->reg().readStringEntry("KEYBINDINGS", "rotate_right", "Ctrl-R");
686 new FXButton(toolbar, TAB+_("Rotate right")+PARS(key)+TAB+_("Rotate right image.")+PARS(key), rotaterighticon, this, ID_ROTATE_270, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
687
688 // Toolbar button: mirror horizontally
689 key = getApp()->reg().readStringEntry("KEYBINDINGS", "mirror_horizontally", "Ctrl-Shift-H");
690 new FXButton(toolbar, TAB+_("Mirror horizontally")+PARS(key)+TAB+_("Mirror image horizontally.")+PARS(key), fliplricon, this, ID_MIRROR_HOR, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
691
692 // Toolbar button: mirror vertically
693 key = getApp()->reg().readStringEntry("KEYBINDINGS", "mirror_vertically", "Ctrl-Shift-V");
694 new FXButton(toolbar, TAB+_("Mirror vertically")+PARS(key)+TAB+_("Mirror image vertically.")+PARS(key), flipudicon, this, ID_MIRROR_VER, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED);
695
696 // File Menu entries
697 FXMenuCommand* mc = NULL;
698 FXString text;
699
700 key = getApp()->reg().readStringEntry("KEYBINDINGS", "open", "Ctrl-O");
701 text = _("&Open...")+TABS(key)+_("Open image file.")+PARS(key);
702 mc = new FXMenuCommand(filemenu, text, fileopenicon, this, ID_OPEN);
703 hotkey = _parseAccel(key);
704 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
705
706 key = getApp()->reg().readStringEntry("KEYBINDINGS", "print", "Ctrl-P");
707 text = _("&Print...")+TABS(key)+_("Print image file.")+PARS(key);
708 mc = new FXMenuCommand(filemenu, text, printicon, this, ID_PRINT);
709 hotkey = _parseAccel(key);
710 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
711
712 // Recent file menu; this automatically hides if there are no files
713 FXMenuSeparator* sep1 = new FXMenuSeparator(filemenu);
714 sep1->setTarget(&mrufiles);
715 sep1->setSelector(FXRecentFiles::ID_ANYFILES);
716 new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_1);
717 new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_2);
718 new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_3);
719 new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_4);
720 new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_5);
721 new FXMenuCommand(filemenu, _("&Clear recent files")+TAB2+_("Clear recent file menu."), NULL, &mrufiles, FXRecentFiles::ID_CLEAR);
722 FXMenuSeparator* sep2 = new FXMenuSeparator(filemenu);
723 sep2->setTarget(&mrufiles);
724 sep2->setSelector(FXRecentFiles::ID_ANYFILES);
725
726 key = getApp()->reg().readStringEntry("KEYBINDINGS", "quit", "Ctrl-Q");
727 text = _("&Quit")+TABS(key)+_("Quit Xfi.")+PARS(key);
728 mc = new FXMenuCommand(filemenu, text, quiticon, this, ID_QUIT);
729 hotkey = _parseAccel(key);
730 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
731 getAccelTable()->addAccel(KEY_Escape, this, FXSEL(SEL_COMMAND, ID_QUIT));
732
733 // Image Menu entries
734 new FXMenuCommand(imagemenu, _("Zoom &in")+TAB+(FXString)"Ctrl+"+TAB+_("Zoom in image.")+PARS("Ctrl+"), zoominicon, this, ID_ZOOM_IN);
735 new FXMenuCommand(imagemenu, _("Zoom &out")+TAB+(FXString)"Ctrl-"+TAB+_("Zoom out image.")+PARS("Ctrl-"), zoomouticon, this, ID_ZOOM_OUT);
736
737 key = getApp()->reg().readStringEntry("KEYBINDINGS", "zoom_100", "Ctrl-I");
738 text = _("Zoo&m 100%")+TABS(key)+_("Zoom image to 100%.")+PARS(key);
739 mc = new FXMenuCommand(imagemenu, text, zoom100icon, this, ID_ZOOM_100);
740 hotkey = _parseAccel(key);
741 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
742
743 key = getApp()->reg().readStringEntry("KEYBINDINGS", "zoom_win", "Ctrl-F");
744 text = _("Zoom to fit &window")+TABS(key)+_("Zoom to fit window.")+PARS(key);
745 mc = new FXMenuCommand(imagemenu, text, zoomwinicon, this, ID_ZOOM_WIN);
746 hotkey = _parseAccel(key);
747 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
748
749 key = getApp()->reg().readStringEntry("KEYBINDINGS", "rotate_right", "Ctrl-R");
750 text = _("Rotate &right")+TABS(key)+_("Rotate right.")+PARS(key);
751 mc = new FXMenuCommand(imagemenu, text, rotaterighticon, this, ID_ROTATE_270);
752 hotkey = _parseAccel(key);
753 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
754
755 key = getApp()->reg().readStringEntry("KEYBINDINGS", "rotate_left", "Ctrl-L");
756 text = _("Rotate &left")+TABS(key)+_("Rotate left.")+PARS(key);
757 mc = new FXMenuCommand(imagemenu, text, rotatelefticon, this, ID_ROTATE_90);
758 hotkey = _parseAccel(key);
759 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
760
761 key = getApp()->reg().readStringEntry("KEYBINDINGS", "mirror_horizontally", "Ctrl-Shift-H");
762 text = _("Mirror &horizontally")+TABS(key)+_("Mirror horizontally.")+PARS(key);
763 mc = new FXMenuCommand(imagemenu, text, fliplricon, this, ID_MIRROR_HOR);
764 hotkey = _parseAccel(key);
765 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
766
767 key = getApp()->reg().readStringEntry("KEYBINDINGS", "mirror_vertically", "Ctrl-Shift-V");
768 text = _("Mirror &vertically")+TABS(key)+_("Mirror vertically.")+PARS(key);
769 mc = new FXMenuCommand(imagemenu, text, flipudicon, this, ID_MIRROR_VER);
770 hotkey = _parseAccel(key);
771 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
772
773 // View Menu entries
774 key = getApp()->reg().readStringEntry("KEYBINDINGS", "hidden_files", "Ctrl-F6");
775 text = _("&Hidden files")+TABS(key)+_("Show hidden files and folders.")+PARS(key);
776 mc = new FXMenuCheck(viewmenu, text, this, ID_TOGGLE_HIDDEN);
777 hotkey = _parseAccel(key);
778 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
779
780 key = getApp()->reg().readStringEntry("KEYBINDINGS", "thumbnails", "Ctrl-F7");
781 text = _("&Thumbnails")+TABS(key)+_("Show image thumbnails.")+PARS(key);
782 mc = new FXMenuCheck(viewmenu, text, this, ID_TOGGLE_THUMBNAILS);
783 hotkey = _parseAccel(key);
784 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
785
786 new FXMenuSeparator(viewmenu);
787
788 key = getApp()->reg().readStringEntry("KEYBINDINGS", "big_icons", "F10");
789 text = _("&Big icons")+TABS(key)+_("Display folders with big icons.")+PARS(key);
790 mc = new FXMenuRadio(viewmenu, text, this, ID_SHOW_BIG_ICONS);
791 hotkey = _parseAccel(key);
792 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
793
794 key = getApp()->reg().readStringEntry("KEYBINDINGS", "small_icons", "F11");
795 text = _("&Small icons")+TABS(key)+_("Display folders with small icons.")+PARS(key);
796 mc = new FXMenuRadio(viewmenu, text, this, ID_SHOW_MINI_ICONS);
797 hotkey = _parseAccel(key);
798 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
799
800 key = getApp()->reg().readStringEntry("KEYBINDINGS", "detailed_file_list", "F12");
801 text = _("&Detailed file list")+TABS(key)+_("Display detailed folder listing.")+PARS(key);
802 mc = new FXMenuRadio(viewmenu, text, this, ID_SHOW_DETAILS);
803 hotkey = _parseAccel(key);
804 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
805
806 new FXMenuSeparator(viewmenu);
807
808 mc = new FXMenuRadio(viewmenu, _("&Vertical panels"), this, XFileImage::ID_VERT_PANELS);
809 key = getApp()->reg().readStringEntry("KEYBINDINGS", "vert_panels", "Ctrl-Shift-F1");
810 mc->setAccelText(key);
811
812 mc = new FXMenuRadio(viewmenu, _("&Horizontal panels"), this, XFileImage::ID_HORZ_PANELS);
813 key = getApp()->reg().readStringEntry("KEYBINDINGS", "horz_panels", "Ctrl-Shift-F2");
814 mc->setAccelText(key);
815
816 new FXMenuSeparator(viewmenu);
817 new FXMenuRadio(viewmenu, _("&Rows")+TAB2+_("View icons row-wise."), filelist, FileList::ID_ARRANGE_BY_ROWS);
818 new FXMenuRadio(viewmenu, _("&Columns")+TAB2+_("View icons column-wise."), filelist, FileList::ID_ARRANGE_BY_COLUMNS);
819 new FXMenuCheck(viewmenu, _("&Autosize")+TAB2+_("Autosize icon names."), filelist, FileList::ID_AUTOSIZE);
820
821 // Preferences menu
822 new FXMenuCheck(prefsmenu, _("&Toolbar")+TAB2+_("Display toolbar."), toolbar, FXWindow::ID_TOGGLESHOWN);
823 new FXMenuCheck(prefsmenu, _("&File list")+TAB2+_("Display file list."), filebox, FXWindow::ID_TOGGLESHOWN);
824 new FXMenuCheck(prefsmenu, _("File list &before")+TAB2+_("Display file list before image window."), this, ID_TOGGLE_FILELIST_BEFORE);
825 new FXMenuCheck(prefsmenu, _("&Filter images")+TAB2+_("List only image files."), this, ID_TOGGLE_FILTER_IMAGES);
826 new FXMenuCheck(prefsmenu, _("Fit &window when opening")+TAB2+_("Zoom to fit window when opening an image."), this, ID_TOGGLE_FIT_WIN);
827
828
829 // Help Menu entries
830 key = getApp()->reg().readStringEntry("KEYBINDINGS", "help", "F1");
831 text = _("&About X File Image")+TABS(key)+_("About X File Image.")+PARS(key);
832 mc = new FXMenuCommand(helpmenu, text, NULL, this, ID_ABOUT, 0);
833 hotkey = _parseAccel(key);
834 getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
835
836 // Close accelerator
837 key = getApp()->reg().readStringEntry("KEYBINDINGS", "close", "Ctrl-W");
838 hotkey = _parseAccel(key);
839 getAccelTable()->addAccel(hotkey, this, FXSEL(SEL_COMMAND, XFileImage::ID_QUIT));
840
841 // Make a tool tip
842 new FXToolTip(getApp(), TOOLTIP_NORMAL);
843
844 // Images
845 img = NULL;
846 tmpimg = NULL;
847
848 // Dialogs
849 printdialog = NULL;
850
851 // Recent files
852 mrufiles.setTarget(this);
853 mrufiles.setSelector(ID_RECENTFILE);
854
855 // Initialize file name
856 filename = "";
857
858 // Initialize some flags
859 fileview = ID_SHOW_MINI_ICONS;
860 hiddenfiles = false;
861
862 // Initialize zoom to 100%
863 indZoom = ZOOM_100;
864 zoomval = zoomtab[indZoom];
865 fitwin = false;
866 filterimgs = false;
867
868 // Initialize previous window width / height
869 prev_width = getWidth();
870 prev_height = getHeight();
871 }
872
873
874 // Clean up
~XFileImage()875 XFileImage::~XFileImage()
876 {
877 delete toolbar;
878 delete menubar;
879 delete statusbar;
880 delete filemenu;
881 delete imagemenu;
882 delete helpmenu;
883 delete prefsmenu;
884 delete viewmenu;
885 delete dragshell1;
886 delete pathlink;
887 delete pathtext;
888 delete filelist;
889 delete img;
890 delete tmpimg;
891 delete printdialog;
892 delete btnbackhist;
893 delete btnforwardhist;
894 }
895
896
onCmdPopupMenu(FXObject * o,FXSelector s,void * p)897 long XFileImage::onCmdPopupMenu(FXObject* o, FXSelector s, void* p)
898 {
899 // Popup menu pane
900 FXMenuPane menu(this);
901 int x, y;
902 FXuint state;
903
904 getRoot()->getCursorPosition(x, y, state);
905
906 new FXMenuCommand(&menu, _("Go ho&me"), homeicon, this, ID_GO_HOME);
907 new FXMenuCommand(&menu, _("Go &work"), workicon, this, ID_GO_WORK);
908 new FXMenuSeparator(&menu);
909 new FXMenuCheck(&menu, _("&Hidden files"), this, ID_TOGGLE_HIDDEN);
910 new FXMenuCheck(&menu, _("Thum&bnails"), this, ID_TOGGLE_THUMBNAILS);
911 new FXMenuSeparator(&menu);
912 new FXMenuRadio(&menu, _("B&ig icons"), this, ID_SHOW_BIG_ICONS);
913 new FXMenuRadio(&menu, _("&Small icons"), this, ID_SHOW_MINI_ICONS);
914 new FXMenuRadio(&menu, _("Fu&ll file list"), this, ID_SHOW_DETAILS);
915 new FXMenuSeparator(&menu);
916 new FXMenuRadio(&menu, _("&Rows"), filelist, FileList::ID_ARRANGE_BY_ROWS);
917 new FXMenuRadio(&menu, _("&Columns"), filelist, FileList::ID_ARRANGE_BY_COLUMNS);
918 new FXMenuCheck(&menu, _("Autosize"), filelist, FileList::ID_AUTOSIZE);
919 new FXMenuSeparator(&menu);
920 new FXMenuRadio(&menu, _("&Name"), filelist, FileList::ID_SORT_BY_NAME);
921 new FXMenuRadio(&menu, _("Si&ze"), filelist, FileList::ID_SORT_BY_SIZE);
922 new FXMenuRadio(&menu, _("&Type"), filelist, FileList::ID_SORT_BY_TYPE);
923 new FXMenuRadio(&menu, _("E&xtension"), filelist, FileList::ID_SORT_BY_EXT);
924 new FXMenuRadio(&menu, _("&Date"), filelist, FileList::ID_SORT_BY_TIME);
925 new FXMenuRadio(&menu, _("&User"), filelist, FileList::ID_SORT_BY_USER);
926 new FXMenuRadio(&menu, _("&Group"), filelist, FileList::ID_SORT_BY_GROUP);
927 new FXMenuRadio(&menu, _("&Permissions"), filelist, FileList::ID_SORT_BY_PERM);
928 new FXMenuSeparator(&menu);
929 new FXMenuCheck(&menu, _("Ignore c&ase"), filelist, FileList::ID_SORT_CASE);
930 new FXMenuCheck(&menu, _("Fold&ers first"), filelist, FileList::ID_DIRS_FIRST);
931 new FXMenuCheck(&menu, _("Re&verse order"), filelist, FileList::ID_SORT_REVERSE);
932
933 menu.create();
934 allowPopupScroll = true; // Allow keyboard scrolling
935 menu.popup(NULL, x, y);
936 getApp()->runModalWhileShown(&menu);
937 allowPopupScroll = false;
938 return(1);
939 }
940
941
942 // If Shift-F10 or Menu is pressed, opens the popup menu
onKeyPress(FXObject * sender,FXSelector sel,void * ptr)943 long XFileImage::onKeyPress(FXObject* sender, FXSelector sel, void* ptr)
944 {
945 FXEvent* event = (FXEvent*)ptr;
946
947 // Shift-F10 or Menu was pressed : open popup menu
948 if ((event->state&SHIFTMASK && event->code == KEY_F10) || event->code == KEY_Menu)
949 {
950 this->handle(sender, FXSEL(SEL_COMMAND, XFileImage::ID_POPUP_MENU), ptr);
951 return(1);
952 }
953
954 // Any other key was pressed : handle the pressed key in the usual way
955 else
956 {
957 if (FXTopWindow::onKeyPress(sender, sel, ptr))
958 {
959 return(1);
960 }
961 }
962
963 return(0);
964 }
965
966
onKeyRelease(FXObject * sender,FXSelector sel,void * ptr)967 long XFileImage::onKeyRelease(FXObject* sender, FXSelector sel, void* ptr)
968 {
969 if (FXTopWindow::onKeyRelease(sender, sel, ptr))
970 {
971 return(1);
972 }
973
974 return(0);
975 }
976
977
978 // User clicked up directory button
onCmdDirUp(FXObject *,FXSelector,void *)979 long XFileImage::onCmdDirUp(FXObject*, FXSelector, void*)
980 {
981 filelist->setDirectory(FXPath::upLevel(filelist->getDirectory()));
982 pathlink->setPath(filelist->getDirectory());
983 pathtext->setText(filelist->getDirectory());
984
985 filelist->setFocus();
986
987 return(1);
988 }
989
990
991 // Can we still go up
onUpdDirUp(FXObject * sender,FXSelector,void *)992 long XFileImage::onUpdDirUp(FXObject* sender, FXSelector, void*)
993 {
994 if (FXPath::isTopDirectory(filelist->getDirectory()))
995 {
996 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), NULL);
997 }
998 else
999 {
1000 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
1001 }
1002 return(1);
1003 }
1004
1005
1006 // Directory back
onCmdDirBack(FXObject *,FXSelector s,void * p)1007 long XFileImage::onCmdDirBack(FXObject*, FXSelector s, void* p)
1008 {
1009 StringList* backhist, *forwardhist;
1010 StringItem* item;
1011 FXString pathname;
1012
1013 // Get the filelist history
1014 backhist = filelist->backhist;
1015 forwardhist = filelist->forwardhist;
1016
1017 // Get the previous directory
1018 item = backhist->getFirst();
1019 if (item)
1020 {
1021 pathname = backhist->getString(item);
1022 }
1023
1024 // Update the history
1025 backhist->removeFirstItem();
1026 forwardhist->insertFirstItem(filelist->getDirectory());
1027
1028 // Go to to the previous directory
1029 filelist->setDirectory(pathname, false);
1030 pathlink->setPath(filelist->getDirectory());
1031 pathtext->setText(filelist->getDirectory());
1032
1033 filelist->setFocus();
1034
1035 return(1);
1036 }
1037
1038
1039 // Update directory back
onUpdDirBack(FXObject * sender,FXSelector sel,void * ptr)1040 long XFileImage::onUpdDirBack(FXObject* sender, FXSelector sel, void* ptr)
1041 {
1042 StringList* backhist;
1043 FXString pathname;
1044
1045 // Get the filelist history
1046 backhist = filelist->backhist;
1047
1048 // Gray out the button if no item in history
1049 if (backhist->getNumItems() == 0)
1050 {
1051 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
1052 }
1053 else
1054 {
1055 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1056 }
1057
1058 return(1);
1059 }
1060
1061
1062 // Directory forward
onCmdDirForward(FXObject *,FXSelector s,void * p)1063 long XFileImage::onCmdDirForward(FXObject*, FXSelector s, void* p)
1064 {
1065 StringList* backhist, *forwardhist;
1066 StringItem* item;
1067 FXString pathname;
1068
1069 // Get the filelist history
1070 backhist = filelist->backhist;
1071 forwardhist = filelist->forwardhist;
1072
1073 // Get the next directory
1074 item = forwardhist->getFirst();
1075 if (item)
1076 {
1077 pathname = forwardhist->getString(item);
1078 }
1079
1080 // Update the history
1081 forwardhist->removeFirstItem();
1082 backhist->insertFirstItem(filelist->getDirectory());
1083
1084 // Go to to the previous directory
1085 filelist->setDirectory(pathname, false);
1086 pathlink->setPath(filelist->getDirectory());
1087 pathtext->setText(filelist->getDirectory());
1088
1089 filelist->setFocus();
1090
1091 return(1);
1092 }
1093
1094
1095 // Update directory forward
onUpdDirForward(FXObject * sender,FXSelector sel,void * ptr)1096 long XFileImage::onUpdDirForward(FXObject* sender, FXSelector sel, void* ptr)
1097 {
1098 StringList* forwardhist;
1099 FXString pathname;
1100
1101 // Get the filelist history
1102 forwardhist = filelist->forwardhist;
1103
1104 // Gray out the button if no item in history
1105 if (forwardhist->getNumItems() == 0)
1106 {
1107 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
1108 }
1109 else
1110 {
1111 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1112 }
1113
1114 return(1);
1115 }
1116
1117
1118 // Directory back history
onCmdDirBackHist(FXObject * sender,FXSelector sel,void * ptr)1119 long XFileImage::onCmdDirBackHist(FXObject* sender, FXSelector sel, void* ptr)
1120 {
1121 StringList* backhist, *forwardhist;
1122 StringItem* item;
1123 FXString pathname;
1124
1125 // Get the filelist history
1126 backhist = filelist->backhist;
1127 forwardhist = filelist->forwardhist;
1128
1129 // Get all string items and display them in a list box
1130 int num = backhist->getNumItems();
1131 if (num > 0)
1132 {
1133 FXString* dirs = new FXString[num];
1134 FXString strlist = "";
1135
1136 // Get string items
1137 item = backhist->getFirst();
1138 for (int i = 0; i <= num-1; i++)
1139 {
1140 if (item)
1141 {
1142 FXString str = backhist->getString(item);
1143 dirs[i] = str;
1144 strlist = strlist+str+"\n";
1145 item = backhist->getNext(item);
1146 }
1147 }
1148
1149 // Display list box
1150 int pos = DirHistBox::box(btnbackhist, DECOR_NONE, strlist, this->getX()+245, this->getY()+37);
1151
1152 // If an item was selected
1153 if (pos != -1)
1154 {
1155 // Update back history
1156 if (pos == num-1)
1157 {
1158 backhist->removeAllItems();
1159 }
1160 else
1161 {
1162 item = backhist->getItemAtPos(pos+1);
1163 backhist->removeAllItemsBefore(item);
1164 }
1165
1166 // Update forward history
1167 forwardhist->insertFirstItem(filelist->getDirectory());
1168 if (pos > 0)
1169 {
1170 for (int i = 0; i <= pos-1; i++)
1171 {
1172 forwardhist->insertFirstItem(dirs[i]);
1173 }
1174 }
1175
1176 // Go to to the selected directory
1177 pathname = dirs[pos];
1178 filelist->setDirectory(pathname, false);
1179 pathlink->setPath(filelist->getDirectory());
1180 pathtext->setText(filelist->getDirectory());
1181 }
1182 delete[]dirs;
1183 }
1184
1185 return(1);
1186 }
1187
1188
1189 // Update directory back
onUpdDirBackHist(FXObject * sender,FXSelector sel,void * ptr)1190 long XFileImage::onUpdDirBackHist(FXObject* sender, FXSelector sel, void* ptr)
1191 {
1192 StringList* backhist;
1193 FXString pathname;
1194
1195 // Get the filelist history
1196 backhist = filelist->backhist;
1197
1198 // Gray out the button if no item in history
1199 if (backhist->getNumItems() == 0)
1200 {
1201 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
1202 }
1203 else
1204 {
1205 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1206 }
1207
1208 return(1);
1209 }
1210
1211
1212 // Directory forward history
onCmdDirForwardHist(FXObject * sender,FXSelector sel,void * ptr)1213 long XFileImage::onCmdDirForwardHist(FXObject* sender, FXSelector sel, void* ptr)
1214 {
1215 StringList* backhist, *forwardhist;
1216 StringItem* item;
1217 FXString pathname;
1218
1219 // Get the filelist history
1220 backhist = filelist->backhist;
1221 forwardhist = filelist->forwardhist;
1222
1223 // Get all string items and display them in a list box
1224 int num = forwardhist->getNumItems();
1225 if (num > 0)
1226 {
1227 FXString* dirs = new FXString[num];
1228 FXString strlist = "";
1229
1230 // Get string items
1231 item = forwardhist->getFirst();
1232 for (int i = 0; i <= num-1; i++)
1233 {
1234 if (item)
1235 {
1236 FXString str = forwardhist->getString(item);
1237 dirs[i] = str;
1238 strlist = strlist+str+"\n";
1239 item = forwardhist->getNext(item);
1240 }
1241 }
1242
1243 // Display list box
1244 int pos = DirHistBox::box(btnforwardhist, DECOR_NONE, strlist, this->getX()+285, this->getY()+37);
1245
1246 // If an item was selected
1247 if (pos != -1)
1248 {
1249 // Update forward history
1250 if (pos == num-1)
1251 {
1252 forwardhist->removeAllItems();
1253 }
1254 else
1255 {
1256 item = forwardhist->getItemAtPos(pos+1);
1257 forwardhist->removeAllItemsBefore(item);
1258 }
1259
1260 // Update back history
1261 backhist->insertFirstItem(filelist->getDirectory());
1262 if (pos > 0)
1263 {
1264 for (int i = 0; i <= pos-1; i++)
1265 {
1266 backhist->insertFirstItem(dirs[i]);
1267 }
1268 }
1269
1270 // Go to to the selected directory
1271 pathname = dirs[pos];
1272 filelist->setDirectory(pathname, false);
1273 pathlink->setPath(filelist->getDirectory());
1274 pathtext->setText(filelist->getDirectory());
1275 }
1276 delete[]dirs;
1277 }
1278
1279 return(1);
1280 }
1281
1282
1283 // Update directory forward
onUpdDirForwardHist(FXObject * sender,FXSelector sel,void * ptr)1284 long XFileImage::onUpdDirForwardHist(FXObject* sender, FXSelector sel, void* ptr)
1285 {
1286 StringList* forwardhist;
1287 FXString pathname;
1288
1289 // Get the filelist history
1290 forwardhist = filelist->forwardhist;
1291
1292 // Gray out the button if no item in history
1293 if (forwardhist->getNumItems() == 0)
1294 {
1295 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
1296 }
1297 else
1298 {
1299 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1300 }
1301
1302 return(1);
1303 }
1304
1305
1306 // Back to home directory
onCmdHome(FXObject *,FXSelector,void *)1307 long XFileImage::onCmdHome(FXObject*, FXSelector, void*)
1308 {
1309 filelist->setDirectory(FXSystem::getHomeDirectory());
1310 pathlink->setPath(filelist->getDirectory());
1311 pathtext->setText(filelist->getDirectory());
1312 filelist->setFocus();
1313 return(1);
1314 }
1315
1316
1317 // Back to current working directory
onCmdWork(FXObject *,FXSelector,void *)1318 long XFileImage::onCmdWork(FXObject*, FXSelector, void*)
1319 {
1320 filelist->setDirectory(FXSystem::getCurrentDirectory());
1321 pathlink->setPath(filelist->getDirectory());
1322 pathtext->setText(filelist->getDirectory());
1323 filelist->setFocus();
1324 return(1);
1325 }
1326
1327
1328 // About box
onCmdAbout(FXObject *,FXSelector,void *)1329 long XFileImage::onCmdAbout(FXObject*, FXSelector, void*)
1330 {
1331 FXString msg;
1332
1333 msg.format(_("X File Image Version %s is a simple image viewer.\n\n"), VERSION);
1334 msg += COPYRIGHT;
1335 MessageBox about(this, _("About X File Image"), msg.text(), xfiicon, BOX_OK|DECOR_TITLE|DECOR_BORDER,
1336 JUSTIFY_CENTER_X|ICON_BEFORE_TEXT|LAYOUT_CENTER_Y|LAYOUT_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
1337 about.execute(PLACEMENT_OWNER);
1338
1339 filelist->setFocus();
1340
1341 return(1);
1342 }
1343
1344
1345 // Load file
loadimage(const FXString & file)1346 FXbool XFileImage::loadimage(const FXString& file)
1347 {
1348 FXString ext = FXPath::extension(file);
1349
1350 FILE* fp = fopen(file.text(), "r");
1351
1352 if (!fp)
1353 {
1354 MessageBox::error(this, BOX_OK, _("Error Loading File"), _("Unable to open file: %s"), file.text());
1355 return(false);
1356 }
1357 else
1358 {
1359 fclose(fp);
1360 }
1361
1362 // Free old image if any, before loading a new one
1363 if (img)
1364 {
1365 delete img;
1366 img = NULL;
1367 }
1368 if (tmpimg)
1369 {
1370 delete tmpimg;
1371 tmpimg = NULL;
1372 }
1373
1374 if (comparecase(ext, "gif") == 0)
1375 {
1376 img = new FXGIFImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1377 tmpimg = new FXGIFImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1378 }
1379 else if (comparecase(ext, "bmp") == 0)
1380 {
1381 img = new FXBMPImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1382 tmpimg = new FXBMPImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1383 }
1384 else if (comparecase(ext, "xpm") == 0)
1385 {
1386 img = new FXXPMImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1387 tmpimg = new FXXPMImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1388 }
1389 else if (comparecase(ext, "pcx") == 0)
1390 {
1391 img = new FXPCXImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1392 tmpimg = new FXPCXImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1393 }
1394 else if ((comparecase(ext, "ico") == 0) || (comparecase(ext, "cur") == 0))
1395 {
1396 img = new FXICOImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1397 tmpimg = new FXICOImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1398 }
1399 else if (comparecase(ext, "tga") == 0)
1400 {
1401 img = new FXTGAImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1402 tmpimg = new FXTGAImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1403 }
1404 else if (comparecase(ext, "rgb") == 0)
1405 {
1406 img = new FXRGBImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1407 }
1408 else if (comparecase(ext, "xbm") == 0)
1409 {
1410 img = new FXXBMImage(getApp(), NULL, NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1411 tmpimg = new FXXBMImage(getApp(), NULL, NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1412 }
1413 else if (comparecase(ext, "ppm") == 0)
1414 {
1415 img = new FXPPMImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1416 tmpimg = new FXPPMImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1417 }
1418 else if (comparecase(ext, "png") == 0)
1419 {
1420 img = new FXPNGImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1421 tmpimg = new FXPNGImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1422 }
1423 else if ((comparecase(ext, "jpg") == 0) || (comparecase(ext, "jpeg") == 0))
1424 {
1425 img = new FXJPGImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1426 tmpimg = new FXJPGImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1427 }
1428 else if ((comparecase(ext, "tif") == 0) || (comparecase(ext, "tiff") == 0))
1429 {
1430 img = new FXTIFImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1431 tmpimg = new FXTIFImage(getApp(), NULL, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
1432 }
1433 else
1434 {
1435 img = NULL;
1436 tmpimg = NULL;
1437 }
1438
1439 // Perhaps failed
1440 if (img == NULL)
1441 {
1442 MessageBox::error(this, BOX_OK, _("Error Loading Image"), _("Unsupported type: %s"), ext.text());
1443 return(false);
1444 }
1445
1446 if (tmpimg == NULL)
1447 {
1448 MessageBox::error(this, BOX_OK, _("Error Loading Image"), _("Unsupported type: %s"), ext.text());
1449 return(false);
1450 }
1451
1452 // Load it
1453 FXFileStream stream;
1454 if (stream.open(file, FXStreamLoad))
1455 {
1456 getApp()->beginWaitCursor();
1457 FXbool res = img->loadPixels(stream);
1458
1459 stream.close();
1460
1461 // If failed
1462 if (!res)
1463 {
1464 MessageBox::error(this, BOX_OK, _("Error Loading Image"), _("Unable to load image, the file may be corrupted"));
1465 getApp()->endWaitCursor();
1466 return(false);
1467 }
1468
1469 if (!FXMEMDUP(&tmpdata, img->getData(), FXColor, img->getWidth()*img->getHeight()))
1470 {
1471 throw FXMemoryException(_("Unable to load image"));
1472 }
1473 tmpimg->setData(tmpdata, IMAGE_OWNED, img->getWidth(), img->getHeight());
1474
1475 img->create();
1476 tmpimg->create();
1477
1478 imageview->setImage(tmpimg);
1479
1480 // Initial zoom and image format
1481 indZoom = ZOOM_100;
1482 zoomval = zoomtab[indZoom];
1483 getApp()->endWaitCursor();
1484
1485 // Zoom to fit window if asked
1486 if (fitwin)
1487 {
1488 handle(this, FXSEL(SEL_COMMAND, ID_ZOOM_WIN), NULL);
1489 }
1490 }
1491 filelist->setDirectory(FXPath::directory(file));
1492 pathlink->setPath(filelist->getDirectory());
1493 pathtext->setText(filelist->getDirectory());
1494
1495 return(true);
1496 }
1497
1498
1499 // Toggle file list before image
onCmdToggleFileListBefore(FXObject * sender,FXSelector,void *)1500 long XFileImage::onCmdToggleFileListBefore(FXObject* sender, FXSelector, void*)
1501 {
1502 filelistbefore = !filelistbefore;
1503
1504 if (BOX_CLICKED_CANCEL != MessageBox::question(this, BOX_OK_CANCEL, _("Restart"), _("Change will be taken into account after restart.\nRestart X File Image now?")))
1505 {
1506 this->handle(this, FXSEL(SEL_COMMAND, XFileImage::ID_RESTART), NULL);
1507 }
1508
1509 return(1);
1510 }
1511
1512
1513 // Update file list before image
onUpdToggleFileListBefore(FXObject * sender,FXSelector,void *)1514 long XFileImage::onUpdToggleFileListBefore(FXObject* sender, FXSelector, void*)
1515 {
1516 if (filebox->shown())
1517 {
1518 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
1519 if (filelistbefore)
1520 {
1521 sender->handle(this, FXSEL(SEL_COMMAND, ID_CHECK), NULL);
1522 }
1523 else
1524 {
1525 sender->handle(this, FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
1526 }
1527 }
1528 else
1529 {
1530 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), NULL);
1531 }
1532
1533 return(1);
1534 }
1535
1536
1537 // Toggle zoom to fit window on startup
onCmdToggleFitWin(FXObject *,FXSelector,void *)1538 long XFileImage::onCmdToggleFitWin(FXObject*, FXSelector, void*)
1539 {
1540 fitwin = !fitwin;
1541 filelist->setFocus();
1542 return(1);
1543 }
1544
1545
1546 // Update toggle wrap mode
onUpdToggleFitWin(FXObject * sender,FXSelector,void *)1547 long XFileImage::onUpdToggleFitWin(FXObject* sender, FXSelector, void*)
1548 {
1549 if (fitwin)
1550 {
1551 sender->handle(this, FXSEL(SEL_COMMAND, ID_CHECK), NULL);
1552 }
1553 else
1554 {
1555 sender->handle(this, FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
1556 }
1557 return(1);
1558 }
1559
1560
1561 // Toggle filter image files
onCmdToggleFilterImages(FXObject *,FXSelector,void *)1562 long XFileImage::onCmdToggleFilterImages(FXObject*, FXSelector, void*)
1563 {
1564 filterimgs = !filterimgs;
1565 if (filterimgs)
1566 {
1567 filelist->setPattern(imgpatterns);
1568 }
1569 else
1570 {
1571 filelist->setPattern("*");
1572 }
1573
1574 filelist->setFocus();
1575
1576 return(1);
1577 }
1578
1579
1580 // Update filter image files
onUpdToggleFilterImages(FXObject * sender,FXSelector,void *)1581 long XFileImage::onUpdToggleFilterImages(FXObject* sender, FXSelector, void*)
1582 {
1583 // Disable menu item if the file list is not shown
1584 if (filebox->shown())
1585 {
1586 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), NULL);
1587
1588 // Update menu item
1589 if (filterimgs)
1590 {
1591 sender->handle(this, FXSEL(SEL_COMMAND, ID_CHECK), NULL);
1592 }
1593 else
1594 {
1595 sender->handle(this, FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
1596 }
1597 }
1598 else
1599 {
1600 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), NULL);
1601
1602 // Update menu item
1603 if (filterimgs)
1604 {
1605 sender->handle(this, FXSEL(SEL_COMMAND, ID_CHECK), NULL);
1606 }
1607 else
1608 {
1609 sender->handle(this, FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
1610 }
1611 }
1612 return(1);
1613 }
1614
1615
1616 // Open
onCmdOpen(FXObject *,FXSelector,void *)1617 long XFileImage::onCmdOpen(FXObject*, FXSelector, void*)
1618 {
1619 FileDialog opendialog(this, _("Open Image"));
1620
1621 opendialog.setSelectMode(SELECTFILE_EXISTING);
1622 opendialog.setPatternList(patterns);
1623 opendialog.setDirectory(filelist->getDirectory());
1624 if (opendialog.execute())
1625 {
1626 filename = opendialog.getFilename();
1627 filelist->setCurrentFile(filename);
1628 mrufiles.appendFile(filename);
1629 loadimage(filename);
1630 }
1631
1632 return(1);
1633 }
1634
1635
1636 // Print the text
onCmdPrint(FXObject *,FXSelector,void *)1637 long XFileImage::onCmdPrint(FXObject*, FXSelector, void*)
1638 {
1639 // Read the current print command from the registry
1640 FXString printcommand, command;
1641
1642 printcommand = getApp()->reg().readStringEntry("OPTIONS", "print_command", "lpr -P printer");
1643
1644 // Open print dialog filled with the current print command
1645 int rc = 1;
1646 if (printdialog == NULL)
1647 {
1648 printdialog = new InputDialog(this, printcommand, _("Print command: \n(ex: lpr -P <printer>)"), _("Print"), "", printbigicon);
1649 }
1650 printdialog->setText(printcommand);
1651 printdialog->CursorEnd();
1652 rc = printdialog->execute(PLACEMENT_CURSOR);
1653 printcommand = printdialog->getText();
1654
1655 // If cancel was pressed, exit
1656 if (!rc)
1657 {
1658 return(0);
1659 }
1660
1661 // Write the new print command to the registry
1662 getApp()->reg().writeStringEntry("OPTIONS", "print_command", printcommand.text());
1663
1664 // Perform the print command
1665 command = "cat " + filename + " |" + printcommand + " &";
1666 int ret = system(command.text());
1667 if (ret < 0)
1668 {
1669 MessageBox::error(this, BOX_OK, _("Error"), _("Can't execute command %s"), command.text());
1670 return(0);
1671 }
1672
1673 return(1);
1674 }
1675
1676
1677 // Handle toggle hidden command
onCmdToggleHidden(FXObject * sender,FXSelector sel,void * ptr)1678 long XFileImage::onCmdToggleHidden(FXObject* sender, FXSelector sel, void* ptr)
1679 {
1680 filelist->handle(sender, FXSEL(SEL_COMMAND, FileList::ID_TOGGLE_HIDDEN), ptr);
1681 filelist->setFocus();
1682
1683 return(1);
1684 }
1685
1686
1687 // Update toggle hidden command
onUpdToggleHidden(FXObject * sender,FXSelector sel,void * ptr)1688 long XFileImage::onUpdToggleHidden(FXObject* sender, FXSelector sel, void* ptr)
1689 {
1690 FXuint msg = FXWindow::ID_UNCHECK;
1691
1692 hiddenfiles = filelist->shownHiddenFiles();
1693
1694 if (hiddenfiles == true)
1695 {
1696 msg = FXWindow::ID_CHECK;
1697 }
1698 sender->handle(this, FXSEL(SEL_COMMAND, msg), ptr);
1699
1700 // Disable menu item if the file list is not shown
1701 if (filebox->shown())
1702 {
1703 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), NULL);
1704 }
1705 else
1706 {
1707 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), NULL);
1708 }
1709
1710 return(1);
1711 }
1712
1713
1714 // Handle toggle hidden command
onCmdToggleThumbnails(FXObject * sender,FXSelector sel,void * ptr)1715 long XFileImage::onCmdToggleThumbnails(FXObject* sender, FXSelector sel, void* ptr)
1716 {
1717 filelist->handle(sender, FXSEL(SEL_COMMAND, FileList::ID_TOGGLE_THUMBNAILS), ptr);
1718 filelist->setFocus();
1719
1720 return(1);
1721 }
1722
1723
1724 // Update toggle hidden command
onUpdToggleThumbnails(FXObject * sender,FXSelector sel,void * ptr)1725 long XFileImage::onUpdToggleThumbnails(FXObject* sender, FXSelector sel, void* ptr)
1726 {
1727 FXuint msg = FXWindow::ID_UNCHECK;
1728
1729 thumbnails = filelist->shownThumbnails();
1730
1731 if (thumbnails == true)
1732 {
1733 msg = FXWindow::ID_CHECK;
1734 }
1735 sender->handle(this, FXSEL(SEL_COMMAND, msg), ptr);
1736
1737 // Disable menu item if the file list is not shown
1738 if (filebox->shown())
1739 {
1740 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), NULL);
1741 }
1742 else
1743 {
1744 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), NULL);
1745 }
1746
1747 return(1);
1748 }
1749
1750
1751 // Show mini icons in file list
onCmdShowMini(FXObject *,FXSelector,void *)1752 long XFileImage::onCmdShowMini(FXObject*, FXSelector, void*)
1753 {
1754 fileview = ID_SHOW_MINI_ICONS;
1755 filelist->handle(this, FXSEL(SEL_COMMAND, FileList::ID_SHOW_MINI_ICONS), NULL);
1756 filelist->setFocus();
1757
1758 return(1);
1759 }
1760
1761
1762 // Show big icons in file list
onCmdShowBig(FXObject *,FXSelector,void *)1763 long XFileImage::onCmdShowBig(FXObject*, FXSelector, void*)
1764 {
1765 fileview = ID_SHOW_BIG_ICONS;
1766 filelist->handle(this, FXSEL(SEL_COMMAND, FileList::ID_SHOW_BIG_ICONS), NULL);
1767 filelist->setFocus();
1768
1769 return(1);
1770 }
1771
1772
1773 // Show details in file list
onCmdShowDetails(FXObject *,FXSelector,void *)1774 long XFileImage::onCmdShowDetails(FXObject*, FXSelector, void*)
1775 {
1776 fileview = ID_SHOW_DETAILS;
1777 filelist->handle(this, FXSEL(SEL_COMMAND, FileList::ID_SHOW_DETAILS), NULL);
1778 filelist->setFocus();
1779
1780 return(1);
1781 }
1782
1783
1784 // Update filelist
onUpdFileView(FXObject * sender,FXSelector sel,void * ptr)1785 long XFileImage::onUpdFileView(FXObject* sender, FXSelector sel, void* ptr)
1786 {
1787 // Keep the filebox width / height relative to the window width / height
1788
1789 // Get the current width and height
1790 int width = getWidth();
1791 int height = getHeight();
1792
1793 // Panel stacked horizontally
1794 if (vertpanels)
1795 {
1796 if (relative_resize && (prev_width != width))
1797 {
1798 // File box shown
1799 if (filebox->shown())
1800 {
1801 filebox->setWidth((int)round(filewidth_pct*width));
1802 }
1803 }
1804
1805 // Update the relative width (only if window width is sufficient)
1806 prev_width = width;
1807 if (getWidth() > 10)
1808 {
1809 filewidth_pct = (double)(filebox->getWidth())/(double)(getWidth());
1810 }
1811 }
1812
1813 // Panel stacked vertically
1814 else
1815 {
1816 if (relative_resize && (prev_height != height))
1817 {
1818 // File box shown
1819 if (filebox->shown())
1820 {
1821 filebox->setHeight((int)round(fileheight_pct*height));
1822 }
1823 }
1824
1825 // Update the relative height (only if window height is sufficient)
1826 prev_height = height;
1827 if (getHeight() > 10)
1828 {
1829 fileheight_pct = (double)(filebox->getHeight())/(double)(getHeight());
1830 }
1831 }
1832
1833 // Update radio buttons
1834 FXuint msg = FXWindow::ID_UNCHECK;
1835
1836 switch (FXSELID(sel))
1837 {
1838 case ID_SHOW_MINI_ICONS:
1839 if (fileview == ID_SHOW_MINI_ICONS)
1840 {
1841 msg = FXWindow::ID_CHECK;
1842 }
1843 break;
1844
1845 case ID_SHOW_BIG_ICONS:
1846 if (fileview == ID_SHOW_BIG_ICONS)
1847 {
1848 msg = FXWindow::ID_CHECK;
1849 }
1850 break;
1851
1852 case ID_SHOW_DETAILS:
1853 if (fileview == ID_SHOW_DETAILS)
1854 {
1855 msg = FXWindow::ID_CHECK;
1856 }
1857 break;
1858 }
1859 sender->handle(this, FXSEL(SEL_COMMAND, msg), NULL);
1860
1861 // Disable menus items if the file list is not shown
1862 if (filebox->shown())
1863 {
1864 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), NULL);
1865 }
1866 else
1867 {
1868 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), NULL);
1869 }
1870
1871 return(1);
1872 }
1873
1874
1875 // Harvest the zombies
onSigHarvest(FXObject *,FXSelector,void *)1876 long XFileImage::onSigHarvest(FXObject*, FXSelector, void*)
1877 {
1878 while (waitpid(-1, NULL, WNOHANG) > 0)
1879 {
1880 }
1881 return(1);
1882 }
1883
1884
1885 // Quit
onCmdQuit(FXObject *,FXSelector,void *)1886 long XFileImage::onCmdQuit(FXObject*, FXSelector, void*)
1887 {
1888 // Save settings
1889 saveConfig();
1890
1891 // Quit
1892 getApp()->exit(EXIT_SUCCESS);
1893 return(1);
1894 }
1895
1896
1897 // Update title (display image size and actual zoom)
onUpdTitle(FXObject * sender,FXSelector,void *)1898 long XFileImage::onUpdTitle(FXObject* sender, FXSelector, void*)
1899 {
1900 FXString title = "Xfi " + filename;
1901 FXImage* image = imageview->getImage();
1902
1903 if (image && (img != NULL))
1904 {
1905 title += " (" + FXStringVal(img->getWidth()) + "x" + FXStringVal(img->getHeight()) + " - " + FXStringVal(zoomval*100) + "%" ")";
1906 }
1907 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE), (void*)&title);
1908 return(1);
1909 }
1910
1911
1912 // Open recent file
onCmdRecentFile(FXObject *,FXSelector,void * ptr)1913 long XFileImage::onCmdRecentFile(FXObject*, FXSelector, void* ptr)
1914 {
1915 filename = (char*)ptr;
1916 filelist->setCurrentFile(filename);
1917 loadimage(filename);
1918 return(1);
1919 }
1920
1921
1922 // Double clicked in the file list
onCmdItemDoubleClicked(FXObject *,FXSelector,void * ptr)1923 long XFileImage::onCmdItemDoubleClicked(FXObject*, FXSelector, void* ptr)
1924 {
1925 int index = (int)(FXival)ptr;
1926
1927 if (0 <= index)
1928 {
1929 if (filelist->isItemDirectory(index))
1930 {
1931 FXString pathname = filelist->getItemPathname(index);
1932
1933 // Does not have access
1934 if (!::isReadExecutable(pathname))
1935 {
1936 MessageBox::error(this, BOX_OK, _("Error"), _(" Permission to: %s denied."), pathname.text());
1937 return(0);
1938 }
1939 filelist->setDirectory(pathname);
1940 pathlink->setPath(pathname);
1941 pathtext->setText(pathname);
1942 }
1943 else if (filelist->isItemFile(index))
1944 {
1945 filename = filelist->getItemPathname(index);
1946 mrufiles.appendFile(filename);
1947 loadimage(filename);
1948 filelist->setCurrentItem(index);
1949 }
1950 }
1951 return(1);
1952 }
1953
1954
1955 // Single clicked in the file list
onCmdItemClicked(FXObject * sender,FXSelector sel,void * ptr)1956 long XFileImage::onCmdItemClicked(FXObject* sender, FXSelector sel, void* ptr)
1957 {
1958 if (single_click != SINGLE_CLICK_NONE)
1959 {
1960 // In detailed mode, avoid single click when cursor is not over the first column
1961 int x, y;
1962 FXuint state;
1963 filelist->getCursorPosition(x, y, state);
1964 FXbool allow = true;
1965 if (!(filelist->getListStyle()&(_ICONLIST_BIG_ICONS|_ICONLIST_MINI_ICONS)) && ((x-filelist->getXPosition()) > filelist->getHeaderSize(0)))
1966 {
1967 allow = false;
1968 }
1969
1970 int index = (int)(FXival)ptr;
1971 if (0 <= index)
1972 {
1973 if ((single_click != SINGLE_CLICK_NONE) && filelist->isItemDirectory(index) && allow)
1974 {
1975 FXString pathname = filelist->getItemPathname(index);
1976
1977 // Does not have access
1978 if (!::isReadExecutable(pathname))
1979 {
1980 MessageBox::error(this, BOX_OK, _("Error"), _(" Permission to: %s denied."), pathname.text());
1981 return(0);
1982 }
1983 filelist->setDirectory(pathname);
1984 pathlink->setPath(pathname);
1985 pathtext->setText(pathname);
1986 }
1987 else if ((single_click == SINGLE_CLICK_DIR_FILE) && filelist->isItemFile(index) && allow)
1988 {
1989 filename = filelist->getItemPathname(index);
1990 mrufiles.appendFile(filename);
1991 loadimage(filename);
1992 filelist->setCurrentItem(index);
1993 }
1994 }
1995 }
1996 return(1);
1997 }
1998
1999
2000 // Rotate image
onCmdRotate(FXObject *,FXSelector sel,void *)2001 long XFileImage::onCmdRotate(FXObject*, FXSelector sel, void*)
2002 {
2003 getApp()->beginWaitCursor();
2004 FXImage* image = imageview->getImage();
2005 switch (FXSELID(sel))
2006 {
2007 case ID_ROTATE_90:
2008
2009 // Rotate the actual image
2010 image->rotate(90);
2011
2012 // Need to also rotate the original image only if the actual size is different
2013 if ((image->getWidth() != img->getWidth()) || (image->getHeight() != img->getHeight()))
2014 {
2015 img->rotate(90);
2016 }
2017 break;
2018
2019 case ID_ROTATE_270:
2020
2021 // Rotate the actual image
2022 image->rotate(270);
2023
2024 // Need to also rotate the original image only if the actual size is different
2025 if ((image->getWidth() != img->getWidth()) || (image->getHeight() != img->getHeight()))
2026 {
2027 img->rotate(270);
2028 }
2029 break;
2030 }
2031 imageview->setImage(image);
2032 filelist->setFocus();
2033 getApp()->endWaitCursor();
2034 return(1);
2035 }
2036
2037
2038 // Update image
onUpdImage(FXObject * sender,FXSelector,void *)2039 long XFileImage::onUpdImage(FXObject* sender, FXSelector, void*)
2040 {
2041 if (imageview->getImage())
2042 {
2043 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), NULL);
2044 }
2045 else
2046 {
2047 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), NULL);
2048 }
2049 return(1);
2050 }
2051
2052
2053 // Mirror image
onCmdMirror(FXObject *,FXSelector sel,void *)2054 long XFileImage::onCmdMirror(FXObject*, FXSelector sel, void*)
2055 {
2056 getApp()->beginWaitCursor();
2057 FXImage* image = imageview->getImage();
2058 switch (FXSELID(sel))
2059 {
2060 case ID_MIRROR_HOR:
2061
2062 // Mirror the actual image
2063 image->mirror(true, false);
2064
2065 // Need to also mirror the original image only if the actual size is different
2066 if ((image->getWidth() != img->getWidth()) || (image->getHeight() != img->getHeight()))
2067 {
2068 img->mirror(true, false);
2069 }
2070 break;
2071
2072 case ID_MIRROR_VER:
2073
2074 // Mirror the actual image
2075 image->mirror(false, true);
2076
2077 // Need to also mirror the original image only if the actual size is different
2078 if ((image->getWidth() != img->getWidth()) || (image->getHeight() != img->getHeight()))
2079 {
2080 img->mirror(false, true);
2081 }
2082 break;
2083 }
2084 imageview->setImage(image);
2085 filelist->setFocus();
2086 getApp()->endWaitCursor();
2087 return(1);
2088 }
2089
2090
2091 // Zoom in image
onCmdZoomIn(FXObject *,FXSelector,void *)2092 long XFileImage::onCmdZoomIn(FXObject*, FXSelector, void*)
2093 {
2094 getApp()->beginWaitCursor();
2095
2096 // Copy the original image into the actual one
2097 if (!FXMEMDUP(&tmpdata, img->getData(), FXColor, img->getWidth()*img->getHeight()))
2098 {
2099 throw FXMemoryException(_("Unable to load image"));
2100 }
2101 tmpimg->setData(tmpdata, IMAGE_OWNED, img->getWidth(), img->getHeight());
2102
2103 // Resize the actual image according to the new zoom factor
2104 indZoom += 1;
2105 if (indZoom > NB_ZOOM-1)
2106 {
2107 indZoom = NB_ZOOM-1;
2108 }
2109 int sx = (int)(tmpimg->getWidth()*zoomtab[indZoom]);
2110 int sy = (int)(tmpimg->getHeight()*zoomtab[indZoom]);
2111
2112 // Scale only if the actual image size is different
2113 if (indZoom == ZOOM_100)
2114 {
2115 imageview->setImage(img);
2116 }
2117 else
2118 {
2119 // Maximum zoom allowed
2120 if ((sx > MAX_IMGSIZE) || (sy > MAX_IMGSIZE))
2121 {
2122 indZoom -= 1;
2123 if (indZoom < 0)
2124 {
2125 indZoom = 0;
2126 }
2127 sx = (int)(tmpimg->getWidth()*zoomtab[indZoom]);
2128 sy = (int)(tmpimg->getHeight()*zoomtab[indZoom]);
2129 }
2130
2131 // Scale image according to the new zoom factor
2132 tmpimg->scale(sx, sy, 1);
2133 imageview->setImage(tmpimg);
2134 }
2135
2136 // Set zoom value for window title
2137 zoomval = zoomtab[indZoom];
2138
2139 filelist->setFocus();
2140 getApp()->endWaitCursor();
2141 return(1);
2142 }
2143
2144
2145 // Zoom out image
onCmdZoomOut(FXObject *,FXSelector,void *)2146 long XFileImage::onCmdZoomOut(FXObject*, FXSelector, void*)
2147 {
2148 getApp()->beginWaitCursor();
2149
2150 // Copy the original image into the actual one
2151 if (!FXMEMDUP(&tmpdata, img->getData(), FXColor, img->getWidth()*img->getHeight()))
2152 {
2153 throw FXMemoryException(_("Unable to load image"));
2154 }
2155 tmpimg->setData(tmpdata, IMAGE_OWNED, img->getWidth(), img->getHeight());
2156
2157 // Resize the image according to the new zoom factor
2158 indZoom -= 1;
2159 if (indZoom < 0)
2160 {
2161 indZoom = 0;
2162 }
2163 int sx = (int)(tmpimg->getWidth()*zoomtab[indZoom]);
2164 int sy = (int)(tmpimg->getHeight()*zoomtab[indZoom]);
2165
2166 // Scale only if the actual image size is different
2167 if (indZoom == ZOOM_100)
2168 {
2169 imageview->setImage(img);
2170 }
2171 else
2172 {
2173 // Scale image according to the new zoom factor
2174 tmpimg->scale(sx, sy, 1);
2175 imageview->setImage(tmpimg);
2176 }
2177
2178 // Set zoom value for window title
2179 zoomval = zoomtab[indZoom];
2180
2181 filelist->setFocus();
2182 getApp()->endWaitCursor();
2183 return(1);
2184 }
2185
2186
2187 // Zoom to 100%
onCmdZoom100(FXObject *,FXSelector,void *)2188 long XFileImage::onCmdZoom100(FXObject*, FXSelector, void*)
2189 {
2190 getApp()->beginWaitCursor();
2191 indZoom = ZOOM_100;
2192 zoomval = zoomtab[indZoom];
2193 imageview->setImage(img);
2194 filelist->setFocus();
2195 getApp()->endWaitCursor();
2196 return(1);
2197 }
2198
2199
2200 // Zoom to fit window
onCmdZoomWin(FXObject *,FXSelector,void *)2201 long XFileImage::onCmdZoomWin(FXObject*, FXSelector, void*)
2202 {
2203 getApp()->beginWaitCursor();
2204
2205 // Window and image sizes
2206 int winw = imageview->getWidth();
2207 int winh = imageview->getHeight();
2208 int w = img->getWidth();
2209 int h = img->getHeight();
2210
2211 // Compute zoom factor
2212 double fitwin;
2213 if (double(w)/double(h) > double(winw)/double(winh))
2214 {
2215 fitwin = 0.98*(double)winw/(double)w;
2216 }
2217 else
2218 {
2219 fitwin = 0.98*(double)winh/(double)h;
2220 }
2221
2222 // Find the most approaching predefined zoom
2223 // This is used in other zoom functions
2224 for (int k = 0; k < NB_ZOOM; k++)
2225 {
2226 if (zoomtab[k] > fitwin)
2227 {
2228 indZoom = k-1;
2229 break;
2230 }
2231 }
2232 if (indZoom < 0)
2233 {
2234 indZoom = 0;
2235 }
2236 if (indZoom >= NB_ZOOM)
2237 {
2238 indZoom = NB_ZOOM-1;
2239 }
2240
2241 // Copy the original image into the actual one
2242 if (!FXMEMDUP(&tmpdata, img->getData(), FXColor, img->getWidth()*img->getHeight()))
2243 {
2244 throw FXMemoryException(_("Unable to load image"));
2245 }
2246 tmpimg->setData(tmpdata, IMAGE_OWNED, img->getWidth(), img->getHeight());
2247
2248 // Resize the image according to the new zoom factor
2249 int sx = (int)(w*fitwin);
2250 int sy = (int)(h*fitwin);
2251
2252 // Scale image according to the new zoom factor
2253 tmpimg->scale(sx, sy, 1);
2254 imageview->setImage(tmpimg);
2255
2256 // Set zoom value for window title
2257 zoomval = fitwin;
2258
2259 filelist->setFocus();
2260 getApp()->endWaitCursor();
2261 return(1);
2262 }
2263
2264
2265 // Restart the application when required
onCmdRestart(FXObject *,FXSelector,void *)2266 long XFileImage::onCmdRestart(FXObject*, FXSelector, void*)
2267 {
2268 saveConfig();
2269
2270 if (fork() == 0) // Child
2271 {
2272 execvp("xfi", args);
2273 }
2274 else // Parent
2275 {
2276 exit(EXIT_SUCCESS);
2277 }
2278 return(1);
2279 }
2280
2281
2282 // Start the ball rolling
start(FXString startimage)2283 void XFileImage::start(FXString startimage)
2284 {
2285 filename = startimage;
2286 if (filename != "")
2287 {
2288 loadimage(filename);
2289 }
2290 }
2291
2292
2293 // Create and show window
create()2294 void XFileImage::create()
2295 {
2296 // Get size and position
2297 FXuint ww = getApp()->reg().readUnsignedEntry("OPTIONS", "width", DEFAULT_WINDOW_WIDTH); // Workaround for a possible bug in some WMs
2298 FXuint hh = getApp()->reg().readUnsignedEntry("OPTIONS", "height", DEFAULT_WINDOW_HEIGHT); // Workaround for a possible bug in some WMs
2299
2300 filewidth_pct = getApp()->reg().readRealEntry("OPTIONS", "filewidth_pct", 0.25);
2301 fileheight_pct = getApp()->reg().readRealEntry("OPTIONS", "fileheight_pct", 0.25);
2302 FXuint fs = getApp()->reg().readIntEntry("OPTIONS", "filesshown", true);
2303
2304 filelist->setDirectory(FXSystem::getCurrentDirectory());
2305 pathlink->setPath(FXSystem::getCurrentDirectory());
2306 pathtext->setText(FXSystem::getCurrentDirectory());
2307
2308 // Display or hide path linker and path text
2309 if (show_pathlink)
2310 {
2311 pathtext->hide();
2312 pathlink->show();
2313 }
2314 else
2315 {
2316 pathlink->hide();
2317 pathtext->show();
2318 }
2319
2320 // Hide tree if asked for
2321 if (!fs)
2322 {
2323 filebox->hide();
2324 }
2325
2326 // Set toolbar status
2327 if (getApp()->reg().readUnsignedEntry("OPTIONS", "showtoolbar", true) == false)
2328 {
2329 toolbar->hide();
2330 }
2331
2332 // Set status bar status
2333 if (getApp()->reg().readUnsignedEntry("OPTIONS", "showstatusbar", true) == false)
2334 {
2335 statusbar->hide();
2336 }
2337
2338 // Set hidden file status
2339 hiddenfiles = getApp()->reg().readUnsignedEntry("OPTIONS", "hiddenfiles", 0);
2340 filelist->showHiddenFiles(hiddenfiles);
2341
2342 // Set thumbnails status
2343 thumbnails = getApp()->reg().readUnsignedEntry("OPTIONS", "thumbnails", 0);
2344 filelist->showThumbnails(thumbnails);
2345
2346 // Set list style
2347 liststyle = getApp()->reg().readUnsignedEntry("OPTIONS", "liststyle", _ICONLIST_MINI_ICONS);
2348 filelist->setListStyle(liststyle|_ICONLIST_BROWSESELECT);
2349
2350 // Set file view
2351 fileview = getApp()->reg().readUnsignedEntry("OPTIONS", "fileview", ID_SHOW_MINI_ICONS);
2352 this->handle(this, FXSEL(SEL_COMMAND, fileview), NULL);
2353
2354 // Set startup zoom
2355 fitwin = getApp()->reg().readUnsignedEntry("OPTIONS", "fitwin", 0);
2356
2357 // Set filter images flag
2358 filterimgs = getApp()->reg().readUnsignedEntry("OPTIONS", "filterimgs", false);
2359
2360 // Set position and position window
2361 if (save_win_pos)
2362 {
2363 int xpos = getApp()->reg().readIntEntry("OPTIONS", "xpos", DEFAULT_WINDOW_XPOS);
2364 int ypos = getApp()->reg().readIntEntry("OPTIONS", "ypos", DEFAULT_WINDOW_YPOS);
2365 position(xpos, ypos, ww, hh);
2366 }
2367 else
2368 {
2369 position(getX(), getY(), ww, hh);
2370 }
2371
2372 FXMainWindow::create();
2373
2374 if (filterimgs)
2375 {
2376 filelist->setPattern(imgpatterns);
2377 }
2378
2379 // Set filebox width or height
2380 if (vertpanels)
2381 {
2382 filebox->setWidth((int)round(filewidth_pct*getWidth()));
2383 }
2384 else
2385 {
2386 filebox->setHeight((int)round(fileheight_pct*getHeight()));
2387 }
2388
2389 // Set focus on file list
2390 filelist->setFocus();
2391
2392 show();
2393
2394
2395 #ifdef STARTUP_NOTIFICATION
2396 startup_completed();
2397 #endif
2398 }
2399
2400
2401 // Switch between vertical and horizontal panels
onCmdHorzVertPanels(FXObject * sender,FXSelector sel,void * ptr)2402 long XFileImage::onCmdHorzVertPanels(FXObject* sender, FXSelector sel, void* ptr)
2403 {
2404 switch (FXSELID(sel))
2405 {
2406 case ID_VERT_PANELS:
2407 splitter->setSplitterStyle(splitter->getSplitterStyle()&~SPLITTER_VERTICAL);
2408 vertpanels = true;
2409 break;
2410
2411 case ID_HORZ_PANELS:
2412 splitter->setSplitterStyle(splitter->getSplitterStyle()|SPLITTER_VERTICAL);
2413 vertpanels = false;
2414 break;
2415 }
2416
2417 filelist->setFocus();
2418
2419 return(1);
2420 }
2421
2422
2423 // Update the horizontal / vertical panel radio menus
onUpdHorzVertPanels(FXObject * sender,FXSelector sel,void * ptr)2424 long XFileImage::onUpdHorzVertPanels(FXObject* sender, FXSelector sel, void* ptr)
2425 {
2426 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), ptr);
2427
2428 if (vertpanels)
2429 {
2430 if (FXSELID(sel) == ID_HORZ_PANELS)
2431 {
2432 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_UNCHECK), ptr);
2433 }
2434 else
2435 {
2436 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_CHECK), ptr);
2437 }
2438 }
2439 else
2440 {
2441 if (FXSELID(sel) == ID_VERT_PANELS)
2442 {
2443 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_UNCHECK), ptr);
2444 }
2445 else
2446 {
2447 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_CHECK), ptr);
2448 }
2449 }
2450
2451 return(1);
2452 }
2453
2454
2455 // Save configuration when quitting
saveConfig()2456 void XFileImage::saveConfig()
2457 {
2458 // Write new window size and position back to registry
2459 getApp()->reg().writeUnsignedEntry("OPTIONS", "width", (FXuint)getWidth());
2460 getApp()->reg().writeUnsignedEntry("OPTIONS", "height", (FXuint)getHeight());
2461
2462 if (save_win_pos)
2463 {
2464 // Account for the Window Manager border size
2465 XWindowAttributes xwattr;
2466 if (XGetWindowAttributes((Display*)getApp()->getDisplay(), this->id(), &xwattr))
2467 {
2468 getApp()->reg().writeIntEntry("OPTIONS", "xpos", getX()-xwattr.x);
2469 getApp()->reg().writeIntEntry("OPTIONS", "ypos", getY()-xwattr.y);
2470 }
2471 else
2472 {
2473 getApp()->reg().writeIntEntry("OPTIONS", "xpos", getX());
2474 getApp()->reg().writeIntEntry("OPTIONS", "ypos", getY());
2475 }
2476 }
2477
2478 // Width and height of filebox
2479 getApp()->reg().writeRealEntry("OPTIONS", "filewidth_pct", (int)(filewidth_pct*100)/100.0);
2480 getApp()->reg().writeRealEntry("OPTIONS", "fileheight_pct", (int)(fileheight_pct*100)/100.0);
2481
2482 // Was filebox shown
2483 getApp()->reg().writeIntEntry("OPTIONS", "filesshown", filebox->shown());
2484
2485 // Toolbar status
2486 if (toolbar->shown())
2487 {
2488 getApp()->reg().writeUnsignedEntry("OPTIONS", "showtoolbar", true);
2489 }
2490 else
2491 {
2492 getApp()->reg().writeUnsignedEntry("OPTIONS", "showtoolbar", false);
2493 }
2494
2495 // Hidden files status
2496 getApp()->reg().writeUnsignedEntry("OPTIONS", "hiddenfiles", hiddenfiles);
2497
2498 // Thumbnails status
2499 getApp()->reg().writeUnsignedEntry("OPTIONS", "thumbnails", thumbnails);
2500
2501 // File view
2502 getApp()->reg().writeUnsignedEntry("OPTIONS", "fileview", fileview);
2503
2504 // List style
2505 getApp()->reg().writeUnsignedEntry("OPTIONS", "liststyle", filelist->getListStyle());
2506
2507 // Startup zoom
2508 getApp()->reg().writeUnsignedEntry("OPTIONS", "fitwin", fitwin);
2509
2510 // Filter images in file list
2511 getApp()->reg().writeUnsignedEntry("OPTIONS", "filterimgs", filterimgs);
2512
2513 // Filelist columns sizes
2514 getApp()->reg().writeUnsignedEntry("OPTIONS", "name_size", filelist->getHeaderSize(0));
2515 getApp()->reg().writeUnsignedEntry("OPTIONS", "size_size", filelist->getHeaderSize(1));
2516 getApp()->reg().writeUnsignedEntry("OPTIONS", "type_size", filelist->getHeaderSize(2));
2517 getApp()->reg().writeUnsignedEntry("OPTIONS", "ext_size", filelist->getHeaderSize(3));
2518 getApp()->reg().writeUnsignedEntry("OPTIONS", "modd_size", filelist->getHeaderSize(4));
2519 getApp()->reg().writeUnsignedEntry("OPTIONS", "user_size", filelist->getHeaderSize(5));
2520 getApp()->reg().writeUnsignedEntry("OPTIONS", "grou_size", filelist->getHeaderSize(6));
2521 getApp()->reg().writeUnsignedEntry("OPTIONS", "attr_size", filelist->getHeaderSize(7));
2522
2523 // Panel stacking
2524 getApp()->reg().writeUnsignedEntry("OPTIONS", "filelist_before", filelistbefore);
2525 getApp()->reg().writeUnsignedEntry("OPTIONS", "vert_panels", vertpanels);
2526
2527 // Get and write sort function for search window
2528 FXString sort_func;
2529 if (filelist->getSortFunc() == filelist->ascendingCase)
2530 {
2531 sort_func = "ascendingCase";
2532 }
2533 if (filelist->getSortFunc() == filelist->ascendingCaseMix)
2534 {
2535 sort_func = "ascendingCaseMix";
2536 }
2537 else if (filelist->getSortFunc() == filelist->descendingCase)
2538 {
2539 sort_func = "descendingCase";
2540 }
2541 else if (filelist->getSortFunc() == filelist->descendingCaseMix)
2542 {
2543 sort_func = "descendingCaseMix";
2544 }
2545 else if (filelist->getSortFunc() == filelist->ascending)
2546 {
2547 sort_func = "ascending";
2548 }
2549 else if (filelist->getSortFunc() == filelist->ascendingMix)
2550 {
2551 sort_func = "ascendingMix";
2552 }
2553 else if (filelist->getSortFunc() == filelist->descending)
2554 {
2555 sort_func = "descending";
2556 }
2557 else if (filelist->getSortFunc() == filelist->descendingMix)
2558 {
2559 sort_func = "descendingMix";
2560 }
2561 else if (filelist->getSortFunc() == filelist->ascendingSize)
2562 {
2563 sort_func = "ascendingSize";
2564 }
2565 else if (filelist->getSortFunc() == filelist->ascendingSizeMix)
2566 {
2567 sort_func = "ascendingSizeMix";
2568 }
2569 else if (filelist->getSortFunc() == filelist->descendingSize)
2570 {
2571 sort_func = "descendingSize";
2572 }
2573 else if (filelist->getSortFunc() == filelist->descendingSizeMix)
2574 {
2575 sort_func = "descendingSizeMix";
2576 }
2577 else if (filelist->getSortFunc() == filelist->ascendingType)
2578 {
2579 sort_func = "ascendingType";
2580 }
2581 else if (filelist->getSortFunc() == filelist->ascendingTypeMix)
2582 {
2583 sort_func = "ascendingTypeMix";
2584 }
2585 else if (filelist->getSortFunc() == filelist->descendingType)
2586 {
2587 sort_func = "descendingType";
2588 }
2589 else if (filelist->getSortFunc() == filelist->descendingTypeMix)
2590 {
2591 sort_func = "descendingTypeMix";
2592 }
2593 else if (filelist->getSortFunc() == filelist->ascendingExt)
2594 {
2595 sort_func = "ascendingExt";
2596 }
2597 else if (filelist->getSortFunc() == filelist->ascendingExtMix)
2598 {
2599 sort_func = "ascendingExtMix";
2600 }
2601 else if (filelist->getSortFunc() == filelist->descendingExt)
2602 {
2603 sort_func = "descendingExt";
2604 }
2605 else if (filelist->getSortFunc() == filelist->descendingExtMix)
2606 {
2607 sort_func = "descendingExtMix";
2608 }
2609 else if (filelist->getSortFunc() == filelist->ascendingTime)
2610 {
2611 sort_func = "ascendingTime";
2612 }
2613 else if (filelist->getSortFunc() == filelist->ascendingTimeMix)
2614 {
2615 sort_func = "ascendingTimeMix";
2616 }
2617 else if (filelist->getSortFunc() == filelist->descendingTime)
2618 {
2619 sort_func = "descendingTime";
2620 }
2621 else if (filelist->getSortFunc() == filelist->descendingTimeMix)
2622 {
2623 sort_func = "descendingTimeMix";
2624 }
2625 else if (filelist->getSortFunc() == filelist->ascendingUser)
2626 {
2627 sort_func = "ascendingUser";
2628 }
2629 else if (filelist->getSortFunc() == filelist->ascendingUserMix)
2630 {
2631 sort_func = "ascendingUserMix";
2632 }
2633 else if (filelist->getSortFunc() == filelist->descendingUser)
2634 {
2635 sort_func = "descendingUser";
2636 }
2637 else if (filelist->getSortFunc() == filelist->descendingUserMix)
2638 {
2639 sort_func = "descendingUserMix";
2640 }
2641 else if (filelist->getSortFunc() == filelist->ascendingGroup)
2642 {
2643 sort_func = "ascendingGroup";
2644 }
2645 else if (filelist->getSortFunc() == filelist->ascendingGroupMix)
2646 {
2647 sort_func = "ascendingGroupMix";
2648 }
2649 else if (filelist->getSortFunc() == filelist->descendingGroup)
2650 {
2651 sort_func = "descendingGroup";
2652 }
2653 else if (filelist->getSortFunc() == filelist->descendingGroupMix)
2654 {
2655 sort_func = "descendingGroupMix";
2656 }
2657 else if (filelist->getSortFunc() == filelist->ascendingPerm)
2658 {
2659 sort_func = "ascendingPerm";
2660 }
2661 else if (filelist->getSortFunc() == filelist->ascendingPermMix)
2662 {
2663 sort_func = "ascendingPermMix";
2664 }
2665 else if (filelist->getSortFunc() == filelist->descendingPerm)
2666 {
2667 sort_func = "descendingPerm";
2668 }
2669 else if (filelist->getSortFunc() == filelist->descendingPermMix)
2670 {
2671 sort_func = "descendingPermMix";
2672 }
2673 else
2674 {
2675 sort_func = "ascendingCase";
2676 }
2677 getApp()->reg().writeStringEntry("OPTIONS", "sort_func", sort_func.text());
2678
2679 // Write registry settings
2680 getApp()->reg().write();
2681 }
2682
2683
2684 // Usage message
2685 #define USAGE_MSG _("\
2686 \nUsage: xfi [options] [image] \n\
2687 \n\
2688 [options] can be any of the following:\n\
2689 \n\
2690 -h, --help Print (this) help screen and exit.\n\
2691 -v, --version Print version information and exit.\n\
2692 \n\
2693 [image] is the path to the image file you want to open on start up.\n\
2694 \n")
2695
2696
2697
2698 // Start the whole thing
main(int argc,char * argv[])2699 int main(int argc, char* argv[])
2700 {
2701 int i;
2702 FXString startimage = "";
2703 const char* appname = "xfi";
2704 const char* xfename = XFEAPPNAME;
2705 const char* vdrname = XFEVDRNAME;
2706 FXbool loadicons;
2707 FXString xmodifiers;
2708
2709 // Get environment variables $HOME, $XDG_DATA_HOME and $XDG_CONFIG_HOME
2710 homedir = FXSystem::getHomeDirectory();
2711 if (homedir == "")
2712 {
2713 homedir = ROOTDIR;
2714 }
2715 xdgdatahome = getenv("XDG_DATA_HOME");
2716 if (xdgdatahome == "")
2717 {
2718 xdgdatahome = homedir + PATHSEPSTRING DATAPATH;
2719 }
2720 xdgconfighome = getenv("XDG_CONFIG_HOME");
2721 if (xdgconfighome == "")
2722 {
2723 xdgconfighome = homedir + PATHSEPSTRING CONFIGPATH;
2724 }
2725
2726 // Detect if an X input method is used
2727 xmodifiers = getenv("XMODIFIERS");
2728 if ((xmodifiers == "") || (xmodifiers == "@im=none"))
2729 {
2730 xim_used = false;
2731 }
2732 else
2733 {
2734 xim_used = true;
2735 }
2736
2737 #ifdef HAVE_SETLOCALE
2738 // Set locale via LC_ALL.
2739 setlocale(LC_ALL, "");
2740 #endif
2741
2742 #if ENABLE_NLS
2743 // Set the text message domain.
2744 bindtextdomain(PACKAGE, LOCALEDIR);
2745 bind_textdomain_codeset(PACKAGE, "utf-8");
2746 textdomain(PACKAGE);
2747 #endif
2748
2749 // Parse basic arguments
2750 for (i = 1; i < argc; ++i)
2751 {
2752 if ((compare(argv[i], "-v") == 0) || (compare(argv[i], "--version") == 0))
2753 {
2754 fprintf(stdout, "%s version %s\n", PACKAGE, VERSION);
2755 exit(EXIT_SUCCESS);
2756 }
2757 else if ((compare(argv[i], "-h") == 0) || (compare(argv[i], "--help") == 0))
2758 {
2759 fprintf(stdout, USAGE_MSG);
2760 exit(EXIT_SUCCESS);
2761 }
2762 else
2763 {
2764 // Start image, if any
2765 startimage = argv[i];
2766 }
2767 }
2768
2769 args = argv;
2770
2771 // Make application
2772 FXApp* application = new FXApp(appname, vdrname);
2773
2774 // Open display
2775 application->init(argc, argv);
2776
2777 // Read the Xfe registry
2778 FXRegistry* reg_xfe = new FXRegistry(xfename, vdrname);
2779 reg_xfe->read();
2780
2781 // Compute integer and fractional scaling factors depending on the monitor resolution
2782 FXint res = reg_xfe->readUnsignedEntry("SETTINGS", "screenres", 100);
2783 scaleint = round(res / 100.0);
2784 scalefrac = FXMAX(1.0, res / 100.0);
2785
2786 // Redefine the default hand cursor depending on the integer scaling factor
2787 FXCursor* hand;
2788 if (scaleint == 1)
2789 {
2790 hand = new FXCursor(application, hand1_bits, hand1_mask_bits, hand1_width, hand1_height, hand1_x_hot, hand1_y_hot);
2791 }
2792 else if (scaleint == 2)
2793 {
2794 hand = new FXCursor(application, hand2_bits, hand2_mask_bits, hand2_width, hand2_height, hand2_x_hot, hand2_y_hot);
2795 }
2796 else
2797 {
2798 hand = new FXCursor(application, hand3_bits, hand3_mask_bits, hand3_width, hand3_height, hand3_x_hot, hand3_y_hot);
2799 }
2800 application->setDefaultCursor(DEF_HAND_CURSOR, hand);
2801
2802 // Load all application icons
2803 FXbool iconpathfound = true;
2804 loadicons = loadAppIcons(application, &iconpathfound);
2805
2806 // Set base color (to change the default base color at first run)
2807 FXColor basecolor = reg_xfe->readColorEntry("SETTINGS", "basecolor", FXRGB(237, 233, 227));
2808 application->setBaseColor(basecolor);
2809
2810 // Set Xfi normal font according to the Xfe registry
2811 FXString fontspec;
2812 fontspec = reg_xfe->readStringEntry("SETTINGS", "font", DEFAULT_NORMAL_FONT);
2813 if (!fontspec.empty())
2814 {
2815 FXFont* normalFont = new FXFont(application, fontspec);
2816 normalFont->create();
2817 application->setNormalFont(normalFont);
2818 }
2819
2820 // Set Xfi file list colors according to the Xfe registry
2821 listbackcolor = reg_xfe->readColorEntry("SETTINGS", "listbackcolor", FXRGB(255, 255, 255));
2822 listforecolor = reg_xfe->readColorEntry("SETTINGS", "listforecolor", FXRGB(0, 0, 0));
2823 highlightcolor = reg_xfe->readColorEntry("SETTINGS", "highlightcolor", FXRGB(238, 238, 238));
2824
2825 // Set single click navigation according to the Xfe registry
2826 single_click = reg_xfe->readUnsignedEntry("SETTINGS", "single_click", SINGLE_CLICK_NONE);
2827
2828 // Set smooth scrolling according to the Xfe registry
2829 FXbool smoothscroll = reg_xfe->readUnsignedEntry("SETTINGS", "smooth_scroll", true);
2830
2831 // Set file list tooltip flag according to the Xfe registry
2832 file_tooltips = reg_xfe->readUnsignedEntry("SETTINGS", "file_tooltips", true);
2833
2834 // Set relative resizing flag according to the Xfe registry
2835 relative_resize = reg_xfe->readUnsignedEntry("SETTINGS", "relative_resize", true);
2836
2837 // Set display pathlinker flag according to the Xfe registry
2838 show_pathlink = reg_xfe->readUnsignedEntry("SETTINGS", "show_pathlinker", true);
2839
2840 // Get value of the window position flag
2841 save_win_pos = reg_xfe->readUnsignedEntry("SETTINGS", "save_win_pos", false);
2842
2843 // Delete the Xfe registry
2844 delete reg_xfe;
2845
2846 // Make window
2847 XFileImage* window = new XFileImage(application, smoothscroll);
2848
2849 // Catch SIGCHLD to harvest zombie child processes
2850 application->addSignal(SIGCHLD, window, XFileImage::ID_HARVEST, true);
2851
2852 // Handle interrupt to save stuff nicely
2853 application->addSignal(SIGINT, window, XFileImage::ID_QUIT);
2854
2855 // Create it
2856 application->create();
2857
2858 // Smooth scrolling
2859 window->setSmoothScroll(smoothscroll);
2860
2861 // Icon path not found
2862 if (!iconpathfound)
2863 {
2864 MessageBox::error(application, BOX_OK, _("Error loading icons"), _("Icon path doesn't exist, icon theme was set back to default. Please check your icon path!") );
2865 }
2866
2867 // Some icons not found
2868 if (!loadicons)
2869 {
2870 MessageBox::error(application, BOX_OK, _("Error loading icons"), _("Unable to load some icons. Please check your icon theme!"));
2871 }
2872
2873 // Tooltips setup time and duration
2874 application->setTooltipPause(TOOLTIP_PAUSE);
2875 application->setTooltipTime(TOOLTIP_TIME);
2876
2877 // Start
2878 window->start(startimage);
2879
2880 // Run
2881 return(application->run());
2882 }
2883