1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <tui/extern.h>
28
29 #include <klib/rc.h>
30 #include <klib/text.h>
31 #include <klib/printf.h>
32 #include <kfs/directory.h>
33 #include <kfs/filetools.h>
34
35 #include <vfs/manager.h>
36 #include <vfs/path.h>
37
38 #include <tui/tui_dlg.h>
39
40 #include <sysalloc.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44
45
native_to_internal(VFSManager * vfs_mgr,const char * native,char * buffer,uint32_t buffer_size,size_t * written)46 rc_t native_to_internal( VFSManager * vfs_mgr, const char * native, char * buffer, uint32_t buffer_size, size_t * written )
47 {
48 VPath * temp_v_path;
49 rc_t rc = VFSManagerMakeSysPath ( vfs_mgr, &temp_v_path, native );
50 if ( rc == 0 )
51 {
52 rc = VPathReadPath ( temp_v_path, buffer, buffer_size, written );
53 VPathRelease ( temp_v_path );
54 }
55 return rc;
56 }
57
58
internal_to_native(VFSManager * vfs_mgr,const char * internal,char * buffer,uint32_t buffer_size,size_t * written)59 rc_t internal_to_native( VFSManager * vfs_mgr, const char * internal, char * buffer, uint32_t buffer_size, size_t * written )
60 {
61 rc_t rc = 0;
62 if ( internal[ 0 ] == '/' && internal[ 1 ] == 0 )
63 {
64 buffer[ 0 ] = '/'; buffer[ 1 ] = 0; *written = 1;
65 }
66 else
67 {
68 VPath * temp_v_path;
69 rc = VFSManagerMakePath ( vfs_mgr, &temp_v_path, "%s", internal );
70 if ( rc == 0 )
71 {
72 rc = VPathReadSysPath ( temp_v_path, buffer, buffer_size, written );
73 VPathRelease ( temp_v_path );
74 }
75 }
76 return rc;
77 }
78
79
set_native_caption(struct KTUIDlg * dlg,VFSManager * vfs_mgr,uint32_t id,const char * internal_path)80 rc_t set_native_caption( struct KTUIDlg * dlg, VFSManager * vfs_mgr, uint32_t id, const char * internal_path )
81 {
82 tui_rect r;
83 rc_t rc = KTUIDlgGetWidgetRect ( dlg, id, &r );
84 if ( rc == 0 )
85 {
86 size_t written = 0;
87 char native[ 4096 ] = "";
88 rc = internal_to_native( vfs_mgr, internal_path, native, sizeof native, &written );
89 if ( rc == 0 )
90 {
91 if ( written <= ( r.w - 2 ) )
92 rc = KTUIDlgSetWidgetCaption ( dlg, id, native );
93 else
94 {
95 size_t written_2;
96 char temp[ 4096 ];
97 uint32_t part = ( r.w - 3 ) / 2;
98 rc = string_printf ( temp, sizeof temp, &written_2,
99 "%.*s ... %s", part, native, &native[ ( written - part ) - 1 ] );
100 if ( rc == 0 )
101 rc = KTUIDlgSetWidgetCaption ( dlg, id, temp );
102 }
103 }
104 }
105 return rc;
106 }
107
108
109 typedef struct dir_callback_ctx
110 {
111 struct KTUIDlg * dlg;
112 const char * str_to_focus;
113 uint32_t widget_id;
114 uint32_t string_id;
115 uint32_t to_focus;
116 bool in_root;
117 } dir_callback_ctx;
118
119
add_str_to_listbox(dir_callback_ctx * dctx,const char * name)120 static rc_t add_str_to_listbox( dir_callback_ctx * dctx, const char * name )
121 {
122 rc_t rc = 0;
123 if ( dctx->in_root )
124 {
125 #ifdef WINDOWS
126 size_t written;
127 char buffer[ 16 ];
128 rc = string_printf( buffer, sizeof buffer, &written, "%s:\\", name );
129 if ( rc == 0 && written > 0 )
130 rc = KTUIDlgAddWidgetString ( dctx->dlg, dctx->widget_id, buffer );
131 #else
132 rc = KTUIDlgAddWidgetString ( dctx->dlg, dctx->widget_id, name );
133 #endif
134 }
135 else
136 rc = KTUIDlgAddWidgetString ( dctx->dlg, dctx->widget_id, name );
137 return rc;
138 }
139
adjust_path(KDirectory * dir,const char * path_in,char * buffer,size_t buffer_size,const char ** path_ptr)140 static rc_t adjust_path( KDirectory * dir, const char * path_in,
141 char * buffer, size_t buffer_size, const char ** path_ptr )
142 {
143 rc_t rc = 0;
144 uint32_t pt = KDirectoryPathType( dir, "%s", path_in );
145 if ( pt != kptDir )
146 {
147 if ( pt == kptFile )
148 {
149 size_t l = string_size( path_in );
150 if ( l >= buffer_size )
151 {
152 rc = RC( rcFS, rcFile, rcValidating, rcParam, rcInvalid );
153 }
154 else
155 {
156 char * p = string_rchr ( path_in, l, '/' );
157 if ( p == NULL )
158 {
159 rc = RC( rcFS, rcFile, rcValidating, rcParam, rcInvalid );
160 }
161 else
162 {
163 size_t pp = ( p - path_in );
164 string_copy ( buffer, buffer_size, path_in, l );
165 buffer[ pp ] = 0;
166 *path_ptr = buffer;
167 }
168 }
169 }
170 else
171 {
172 rc = RC( rcFS, rcFile, rcValidating, rcParam, rcInvalid );
173 }
174 }
175 else
176 {
177 *path_ptr = path_in;
178 }
179 return rc;
180 }
181
fill_widget_with_dirs(struct KTUIDlg * dlg,KDirectory * dir,uint32_t id,const char * path,const char * to_focus,bool clear)182 rc_t fill_widget_with_dirs( struct KTUIDlg * dlg, KDirectory * dir, uint32_t id,
183 const char * path, const char * to_focus, bool clear )
184 {
185 rc_t rc = 0;
186 char buffer[ 4096 ];
187 const char *path_ptr;
188
189 dir_callback_ctx dctx;
190 dctx.string_id = 0;
191 dctx.to_focus = 0;
192 dctx.str_to_focus = to_focus;
193 dctx.in_root = ( ( path[ 0 ] == '/' )&&( path[ 1 ] == 0 ) );
194 dctx.dlg = dlg;
195 dctx.widget_id = id;
196
197 if ( clear )
198 {
199 rc = KTUIDlgRemoveAllWidgetStrings ( dlg, id );
200 if ( rc == 0 )
201 {
202 if ( !dctx.in_root )
203 {
204 rc = KTUIDlgAddWidgetString ( dlg, id, "[ .. ]" );
205 dctx.string_id++;
206 }
207 }
208 }
209
210 if ( rc == 0 )
211 {
212 /* check if path is actually a file-path, if not look if it is a file-name,
213 in this case extract the path... */
214 rc = adjust_path( dir, path, buffer, sizeof buffer, &path_ptr );
215 }
216
217 if ( rc == 0 )
218 {
219 VNamelist * dir_list;
220 rc = ReadDirEntriesIntoToNamelist( &dir_list, dir, true, false, true, path_ptr );
221 if ( rc == 0 )
222 {
223 uint32_t idx, count;
224 rc = VNameListCount( dir_list, &count );
225 for ( idx = 0; rc == 0 && idx < count; ++idx )
226 {
227 const char * name = NULL;
228 rc = VNameListGet( dir_list, idx, &name );
229 if ( rc == 0 && name != NULL )
230 {
231 rc = add_str_to_listbox( &dctx, name );
232 if ( rc == 0 )
233 {
234 if ( dctx.str_to_focus != NULL )
235 {
236 int cmp = string_cmp ( name, string_size( name ),
237 dctx.str_to_focus, string_size( dctx.str_to_focus ), 4096 );
238 if ( cmp == 0 )
239 dctx.to_focus = dctx.string_id;
240 }
241 dctx.string_id++;
242 }
243 }
244 }
245 VNamelistRelease( dir_list );
246 }
247 }
248
249 if ( rc == 0 && dctx.to_focus > 0 )
250 rc = KTUIDlgSetWidgetSelectedString ( dlg, id, dctx.to_focus );
251
252 return rc;
253 }
254
255
fill_widget_with_files(struct KTUIDlg * dlg,KDirectory * dir,uint32_t id,const char * path,const char * extension,bool clear)256 rc_t fill_widget_with_files( struct KTUIDlg * dlg, KDirectory * dir, uint32_t id,
257 const char * path, const char * extension, bool clear )
258 {
259 rc_t rc = 0;
260 char buffer[ 4096 ];
261 const char *path_ptr;
262
263 if ( clear )
264 {
265 rc = KTUIDlgRemoveAllWidgetStrings ( dlg, id );
266 }
267
268 if ( rc == 0 )
269 {
270 /* check if path is actually a file-path, if not look if it is a file-name,
271 in this case extract the path... */
272 rc = adjust_path( dir, path, buffer, sizeof buffer, &path_ptr );
273 }
274
275 if ( rc == 0 )
276 {
277 VNamelist * file_list;
278 rc = ReadDirEntriesIntoToNamelist( &file_list, dir, true, true, false, path_ptr );
279 if ( rc == 0 )
280 {
281 uint32_t idx, count;
282 rc = VNameListCount( file_list, &count );
283 for ( idx = 0; rc == 0 && idx < count; ++idx )
284 {
285 const char * name = NULL;
286 rc = VNameListGet( file_list, idx, &name );
287 if ( rc == 0 && name != NULL && name[ 0 ] != 0 && name[ 0 ] != '.' )
288 {
289 bool add = ( extension == NULL );
290 if ( !add )
291 {
292 size_t name_size = string_size ( name );
293 size_t ext_size = string_size ( extension );
294 if ( name_size > ext_size )
295 {
296 int cmp = string_cmp ( &name[ name_size - ext_size ], ext_size,
297 extension, ext_size, (uint32_t)ext_size );
298 add = ( cmp == 0 );
299 }
300 }
301 if ( add )
302 rc = KTUIDlgAddWidgetString( dlg, id, name );
303 }
304 }
305 VNamelistRelease( file_list );
306 }
307 }
308 return rc;
309 }
310