1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12
13
14
15 #ifdef OS2
16 #define INCL_DOS
17 #include <os2.h>
18 #endif
19
20
21 #include <Xm/Xm.h>
22 #include <Xm/FileSB.h>
23 #include <Xm/DialogS.h>
24 #include <Xm/Text.h>
25 #include <Xm/SelectioB.h>
26 #include <Xm/Protocols.h>
27 #include <Xm/AtomMgr.h>
28
29 #include "FileDialog.h"
30 #include "Application.h"
31 #include "DXStrings.h"
32 #include "ErrorDialogManager.h"
33
34 #ifdef DXD_WIN /* ajay */
35 #include <direct.h>
36 #include <io.h>
37 #include "DXStrings.h"
38 #endif
39
40 #if 0 //SMH define local X routine
41 extern "C" { extern void ForceUpdate(Widget); }
42 #endif
43
44 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
45 extern "C" {
46 char *KillRelPaths(char *p);
47 void NonUnixQualifySearchProc(Widget w, XtPointer *in_data, XtPointer *out_data);
48 void NonUnixSearchProc(Widget w, XtPointer search_data);
49 void NonUnixDirSearchProc(Widget w, XtPointer search_data);
50 const char *GetNullStr(XmString str);
51 }
52 #endif
53
54 //
55 // These are never installed by this class (on instances of this class)
56 // as this is an abstract class. The subclasses are responsible for
57 // installing these resources, using setDefaultResources().
58 //
59 String FileDialog::DefaultResources[] =
60 {
61 ".dialogStyle: XmDIALOG_FULL_APPLICATION_MODAL",
62 "*pathMode: XmPATH_MODE_FULL",
63 NULL
64 };
65
66 boolean FileDialog::ClassInitialized = FALSE;
67
FileDialog(const char * name,Widget parent)68 FileDialog::FileDialog(const char *name, Widget parent) :
69 Dialog(name, parent)
70 {
71 this->hasCommentButton = FALSE;
72 this->readOnlyDirectory = NULL;
73 }
74
~FileDialog()75 FileDialog::~FileDialog()
76 {
77 if (this->readOnlyDirectory)
78 delete this->readOnlyDirectory;
79 }
80
installDefaultResources(Widget baseWidget)81 void FileDialog::installDefaultResources(Widget baseWidget)
82 {
83 this->setDefaultResources(baseWidget, FileDialog::DefaultResources);
84 this->Dialog::installDefaultResources( baseWidget);
85 }
post()86 void FileDialog::post()
87 {
88 Widget text;
89
90 theApplication->setBusyCursor(TRUE);
91 if (this->getRootWidget() == NULL)
92 {
93 this->initialize();
94 this->setRootWidget(this->createDialog(this->parent));
95
96 Widget shell = XtParent(this->getRootWidget());
97 XtVaSetValues(shell, XmNdeleteResponse, XmDO_NOTHING, NULL);
98 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay(shell),
99 "WM_DELETE_WINDOW", False);
100 XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW,
101 (XtCallbackProc)Dialog_CancelCB,
102 (void *)(this));
103
104 XtAddCallback(this->fsb,
105 XmNokCallback,
106 (XtCallbackProc)Dialog_OkCB,
107 (XtPointer)this);
108
109 XtAddCallback(this->fsb,
110 XmNcancelCallback,
111 (XtCallbackProc)Dialog_CancelCB,
112 (XtPointer)this);
113
114 Widget helpButton =
115 XmFileSelectionBoxGetChild(this->fsb, XmDIALOG_HELP_BUTTON);
116 XtRemoveAllCallbacks(helpButton, XmNactivateCallback);
117 XtAddCallback(helpButton,
118 XmNactivateCallback,
119 (XtCallbackProc)Dialog_HelpCB,
120 (XtPointer)this);
121
122
123 text = XmFileSelectionBoxGetChild(this->fsb, XmDIALOG_TEXT);
124 this->manage();
125 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
126 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
127
128 }
129 this->manage();
130 theApplication->setBusyCursor(FALSE);
131 }
132
133 //
134 // Set the name of the current file.
135 //
setFileName(const char * file)136 void FileDialog::setFileName(const char *file)
137 {
138 ASSERT(this->fsb);
139 XmString xmdir = NULL;
140 char *path = NULL, *dir = NULL;
141
142 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
143 if (!(file[0] == '\\' || file[0] == '/' || (STRLEN(file) > 1 && file[1] == ':'))) {
144 /* if (!strrchr(file, '\\') && !strrchr(file, ':') && !strrchr(file, '/')) { */
145 #else
146 if (file[0] != '/') {
147 #endif
148 XtVaGetValues(this->fsb,XmNdirectory, &xmdir, NULL);
149 XmStringGetLtoR(xmdir,XmSTRING_DEFAULT_CHARSET, &dir);
150
151 path = new char [STRLEN(dir) + 2 + STRLEN(file)];
152
153 sprintf(path,"%s%s",dir,file);
154 file = path;
155 }
156
157 Widget dialog_text = XmSelectionBoxGetChild(this->fsb, XmDIALOG_TEXT);
158
159
160 // DOS2UNIXPATH((char *) file);
161 XmTextSetString(dialog_text, (char*)file);
162
163 //
164 // Right justify the text in the text window.
165 //
166 int len = STRLEN(file);
167 XmTextShowPosition(dialog_text,len);
168 XmTextSetInsertionPosition(dialog_text,len);
169
170
171
172 if (path) delete path;
173 if (dir) XtFree(dir);
174 if (xmdir) XmStringFree(xmdir);
175
176 }
177 //
178 // Get the name of the currently selected file.
179 // The returned string must be freed by the caller.
180 // If a filename is not currently selected, then return NULL.
181 //
182 char *FileDialog::getSelectedFileName()
183 {
184 ASSERT(this->fsb);
185 char *p, *s = XmTextGetString(XmSelectionBoxGetChild(this->fsb,
186 XmDIALOG_TEXT));
187 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
188 char *q = strrchr(s,'\\');
189 p = strrchr(s,'/');
190 if (q && q>p)
191 p = q;
192 #else
193 p = strrchr(s,'/');
194 #endif
195 if (p) {
196 p++;
197 if (!*p) {
198 XtFree(s);
199 s = NULL;
200 }
201 }
202 return s;
203 }
204
205 //
206 // Get the name of the current directory (without a trailing '/').
207 // The returned string must be freed by the caller.
208 //
209 char *FileDialog::getCurrentDirectory()
210 {
211 ASSERT(this->fsb);
212 char *dir = NULL;
213 XmString xmdir;
214
215 XtVaGetValues(this->fsb,XmNdirectory, &xmdir, NULL);
216 if (xmdir) {
217 XmStringGetLtoR(xmdir,XmSTRING_DEFAULT_CHARSET, &dir);
218 char* cp = DuplicateString(dir);
219 XtFree(dir);
220 dir = cp;
221 XmStringFree(xmdir);
222 int last = STRLEN(dir) - 1;
223 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
224 if ((last >= 0) && ((dir[last] == '\\') || (dir[last] == '/')))
225 #else
226 if ((last >= 0) && (dir[last] == '/'))
227 #endif
228 dir[last] = '\0';
229 } else {
230 dir = DuplicateString(".");
231 }
232
233 // DOS2UNIXPATH(dir);
234 return dir;
235 }
236
237 boolean FileDialog::okCallback(Dialog *d)
238 {
239 char *string;
240
241 string = this->getSelectedFileName();
242
243 if (!string) {
244 ModalErrorMessage(this->getRootWidget(),"A filename must be given");
245 return FALSE;
246 }
247
248 this->unmanage();
249 theApplication->setBusyCursor(TRUE);
250 this->okFileWork(string);
251 theApplication->setBusyCursor(FALSE);
252 XtFree(string);
253 return FALSE; // Already unmanaged above
254 }
255
256 Widget FileDialog::createDialog(Widget parent)
257 {
258 Widget shell;
259 Arg wargs[10];
260 int n;
261 char shellname[512];
262
263 n = 0;
264 XtSetArg(wargs[n], XmNallowShellResize, True); n++;
265 sprintf(shellname,"%sShell",this->name);
266 shell = XmCreateDialogShell(parent, shellname, wargs, n);
267
268 //
269 // Motif FileSelection dialogs don't tolerate being sized to tiny
270 // dimensions. They're not able to lay themselves out following
271 // such a resize. So impose min sizes. It might be better to
272 // make a virtual method in Dialog.
273 //
274 XtVaSetValues (shell, XmNminWidth, 130, XmNminHeight, 320, NULL);
275
276 this->fsb = this->createFileSelectionBox(shell, this->name);
277
278 return this->fsb;
279 }
280
281 //
282 // Create the file selection box (i.e. the part with the filter, directory
283 // and file list boxes, and the 4 buttons, ok, comment, cancel, apply).
284 // The four buttons are set the have a width of 120
285 //
286
287 Widget FileDialog::createFileSelectionBox(Widget parent, const char *name)
288 {
289 Widget button;
290 Dimension width;
291
292 Widget fsb = XtVaCreateWidget(name,
293 xmFileSelectionBoxWidgetClass, parent,
294 #if 0
295 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
296 XmNfileSearchProc, NonUnixSearchProc,
297 XmNdirSearchProc, NonUnixDirSearchProc,
298 XmNqualifySearchDataProc, NonUnixQualifySearchProc,
299 #endif
300 #endif
301 NULL);
302
303 if (!this->hasCommentButton) {
304 button = XmFileSelectionBoxGetChild(fsb, XmDIALOG_HELP_BUTTON);
305 XtUnmanageChild(button);
306 }
307
308 //
309 // Ensure the buttons are at least 120 wide
310 //
311 button = XmFileSelectionBoxGetChild(fsb, XmDIALOG_OK_BUTTON);
312 XtVaGetValues(button, XmNwidth, &width, NULL);
313 if (width < 120)
314 {
315 XtVaSetValues(button, XmNwidth, 120, XmNrecomputeSize, False, NULL);
316
317 button = XmFileSelectionBoxGetChild(fsb, XmDIALOG_CANCEL_BUTTON);
318 XtVaSetValues(button, XmNwidth, 120, XmNrecomputeSize, False, NULL);
319
320 button = XmFileSelectionBoxGetChild(fsb, XmDIALOG_APPLY_BUTTON);
321 XtVaSetValues(button, XmNwidth, 120, XmNrecomputeSize, False, NULL);
322
323 button = XmFileSelectionBoxGetChild(fsb, XmDIALOG_HELP_BUTTON);
324 XtVaSetValues(button, XmNwidth, 120, XmNrecomputeSize, False, NULL);
325 }
326
327 return fsb;
328 }
329
330 void FileDialog::manage()
331 {
332 XmFileSelectionDoSearch(this->getFileSelectionBox(), NULL);
333 #if 0 // SMH hack the loop away
334 ForceUpdate(this->fsb);
335 #endif
336 this->displayLimitedMode(this->readOnlyDirectory != NULL);
337 this->Dialog::manage();
338 char *file = this->getDefaultFileName();
339 if (file) {
340 this->setFileName(file);
341 delete file;
342 }
343
344
345 }
346
347 //
348 // If dirname is not NULL, then set the dialog so that the directory is
349 // fixed. If dirname is NULL, then the fixed directory is turned off.
350 //
351 void FileDialog::setReadOnlyDirectory(const char *dirname)
352 {
353 if (this->readOnlyDirectory)
354 delete this->readOnlyDirectory;
355
356 if (dirname) {
357 this->readOnlyDirectory = DuplicateString(dirname);
358 } else {
359 this->readOnlyDirectory = NULL;
360 }
361
362
363 if (this->isManaged()) {
364 XmString string = XmStringCreate((char*)dirname,
365 XmSTRING_DEFAULT_CHARSET);
366 XtVaSetValues(this->fsb, XmNdirectory,string, NULL);
367 XmStringFree(string);
368 this->displayLimitedMode(TRUE);
369 }
370
371 }
372
373 //
374 // If 'limit' is true, change the dialog box so that it operates in
375 // limited mode, that is, the user can only select file from the
376 // current directory specified by XmNdirectory.
377 //
378 void FileDialog::displayLimitedMode(boolean limit)
379 {
380 Widget w[10];
381 int n = 0;
382
383 ASSERT(this->fsb);
384 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_APPLY_BUTTON);
385 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_FILTER_LABEL);
386 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_FILTER_TEXT);
387 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_DIR_LIST_LABEL);
388 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_DIR_LIST);
389 w[n] = XtParent(w[n-1]); n++;
390 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_TEXT);
391 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_SELECTION_LABEL);
392 w[n++] = XmFileSelectionBoxGetChild(this->fsb,XmDIALOG_LIST_LABEL);
393
394 if (limit) {
395 while (n--)
396 XtUnmanageChild(w[n]);
397 } else {
398 while (n--)
399 XtManageChild(w[n]);
400 }
401 }
402
403 //
404 // Get the default file name that is to be placed in the filename text
405 // each time this is FileDialog::manage()'d. By default this returns
406 // NULL and nothing happens. Subclasses can implement this to acquire
407 // the described behavior.
408 //
409 char *FileDialog::getDefaultFileName()
410 {
411 return NULL;
412 }
413
414
415 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
416
417 extern "C" char *KillRelPaths(char *p)
418 {
419 char *s,*p1;
420
421 if (p)
422 {
423 while (!strncmp(p,"/../",4))
424 memmove(p, &p[3], strlen(&p[3])+1);
425 while ((p1=s=strstr(p,"/../")) && s!=p)
426 {
427 s--;
428 while (s!=p && *s != '/')
429 s--;
430 if (*s == '/')
431 memmove(s, &p1[3], strlen(&p1[3])+1);
432 }
433 while (s=strstr(p,"/./"))
434 memmove(s, &s[2], strlen(&s[2])+1);
435 }
436 return p;
437 }
438
439 extern "C" void NonUnixQualifySearchProc(Widget w, XtPointer *in_data, XtPointer *out_data)
440 {
441 Widget u;
442 char *s1,*s2,*s3,*s4;
443 char dir[_MAX_PATH];
444 char mask[_MAX_PATH];
445 char value[_MAX_PATH];
446 char buff[_MAX_PATH];
447 char filter[_MAX_PATH];
448 ULONG PathLength;
449 char *ptr;
450 XmString ext;
451 int i;
452
453
454 #ifndef DXD_WIN
455 APIRET rc;
456 #endif
457
458 XmFileSelectionBoxCallbackStruct *cbs =
459 (XmFileSelectionBoxCallbackStruct *) in_data;
460 XmFileSelectionBoxCallbackStruct *cbs2 =
461 (XmFileSelectionBoxCallbackStruct *) out_data;
462
463 u = XmFileSelectionBoxGetChild(w, XmDIALOG_FILTER_TEXT);
464 s1 = XmTextGetString(u);
465
466 if (s1 && *s1)
467 i = ((*s1 == '/') || (*s1 == '\\') || (strlen(s1)>1 && s1[1] == ':'));
468 else
469 i = 0;
470
471 if (!i)
472 {
473 PathLength=sizeof(mask);
474 #ifdef os2 // ajay
475 rc = DosQueryCurrentDir(0, mask, &PathLength);
476 #endif
477 #ifdef DXD_WIN
478 _getdcwd(0, mask, PathLength - 1);
479 #endif
480 if (mask[strlen(mask)-1] != '\\')
481 strcat(mask, "\\");
482 strcpy(filter, GetNullStr(cbs->mask));
483 strcat(mask, filter);
484 }
485 else
486 strcpy(mask, s1);
487
488 XtFree(s1);
489 DOS2UNIXPATH(mask);
490 if (*mask != '/' && !strchr(mask,':')) /* put leading / */
491 {
492 PathLength=sizeof(buff);
493 strcat(buff,mask);
494 strcpy(mask,buff);
495 }
496 strcpy(dir,mask); /* get dir from mask */
497
498 ptr=strrchr(dir,'/');
499 if(!ptr) ptr = strrchr(dir, ':');
500
501 if (ptr)
502 {
503 strcpy(filter,&ptr[1]); /* get filter from filter text */
504 ptr[1]='\0';
505 }
506 else
507 {
508 strcpy(filter,"*");
509 strcat(dir,"/");
510 }
511
512 if (!cbs->event && cbs->dir) /* clicked on dir selection */
513 {
514 XmStringGetLtoR(cbs->dir, XmFONTLIST_DEFAULT_TAG, &s1);
515 strcpy(mask,s1);
516 XtFree(s1);
517 DOS2UNIXPATH(mask);
518 strcat(mask,"/");
519 if (*mask != '/' && !strchr(mask,':'))
520 {
521 strcpy(buff,"/");
522 strcat(buff,mask);
523 strcpy(mask,buff);
524 }
525 strcpy(dir,mask);
526 strcat(mask, filter);
527 }
528
529 u = XmFileSelectionBoxGetChild(w, XmDIALOG_TEXT);
530 s2 = XmTextGetString(u);
531 if (!s2 || !strlen(s2))
532 strcpy(value,mask);
533 else
534 strcpy(value,s2);
535 XtFree(s2);
536
537 KillRelPaths(mask);
538 KillRelPaths(dir);
539 KillRelPaths(value);
540
541 cbs2->reason = cbs->reason;
542 cbs2->event = cbs->event;
543 cbs2->value = XmStringCreateLocalized(value);
544 cbs2->length = XmStringLength(cbs2->value);
545 cbs2->mask = XmStringCreateLocalized(mask);
546 cbs2->mask_length = XmStringLength(cbs2->mask);
547 cbs2->dir = XmStringCreateLocalized(dir);
548 cbs2->dir_length = XmStringLength(cbs2->dir);
549 cbs2->pattern = XmStringCreateLocalized(filter);
550 cbs2->pattern_length = XmStringLength(cbs2->pattern);
551
552 }
553
554 #ifdef DXD_WIN
555
556 #define MAX_DIR_LIST 256
557
558 extern "C" static int LocalFileCmp(const void *a, const void *b)
559 {
560 return strcmp(*(char **)a, *(char **)b);
561 }
562
563 extern "C" static int GetSortedList(char *mask, char *dir, char **list, int max, int dirs)
564 {
565 struct _finddata_t DirHandle;
566 long HFile;
567 long rc;
568 char *p;
569 int k = 0;
570
571 HFile = _findfirst(mask, &DirHandle );
572 if (HFile == -1L)
573 rc = -1;
574 else
575 rc = 0;
576
577 while (!rc) {
578 if ((dirs == 0) != ((DirHandle.attrib & _A_SUBDIR) == 0)){
579 rc = _findnext(HFile, &DirHandle);
580 continue;
581 }
582 list[k] = (char *)malloc(_MAX_PATH * sizeof(char));
583 p = list[k++];
584
585 strcpy(p, dir);
586 strcat(p, DirHandle.name);
587
588 DOS2UNIXPATH(p);
589
590 rc = _findnext(HFile, &DirHandle);
591 }
592 if (k>1)
593 qsort(list, k, sizeof(char *), LocalFileCmp);
594
595 return k;
596 }
597 #endif // DXD_WIN
598
599 extern "C" void NonUnixSearchProc(Widget w, XtPointer search_data)
600 {
601 char *mask;
602 char fullname[300];
603 char *dir;
604 XmString names[MAX_DIR_LIST];
605 int i=0;
606 #ifndef DXD_WIN /* ajay */
607 HDIR DirHandle=1;
608 FILEFINDBUF3 FindBuffer;
609 APIRET rc;
610 #endif
611 #ifdef DXD_WIN /* ajay */
612 long rc;
613 char *list[MAX_DIR_LIST];
614 int knt;
615 #endif
616 int FindCount = 0;
617 XmFileSelectionBoxCallbackStruct *cbs =
618 (XmFileSelectionBoxCallbackStruct *) search_data;
619
620 malloc(28);
621
622 if (!XmStringGetLtoR(cbs->mask, XmFONTLIST_DEFAULT_TAG, &mask))
623 return;
624 if (!XmStringGetLtoR(cbs->dir, XmFONTLIST_DEFAULT_TAG, &dir))
625 return;
626
627 UNIX2DOSPATH(mask);
628
629 #ifdef os2 // ajay
630 rc = DosFindFirst(mask, &DirHandle, FILE_READONLY, (PVOID) &FindBuffer,
631 sizeof(FindBuffer), &FindCount, FIL_STANDARD);
632
633 XtFree(mask);
634 while(!rc && i<MAX_DIR_LIST){
635 /* DosQueryPathInfo(Findbuffer.achName, FIL_QUERYFULLNAME,
636 fullname, sizeof(fullname)); */
637 strcpy(fullname,dir);
638 strcat(fullname,FindBuffer.achName);
639
640 DOS2UNIXPATH(fullname);
641 names[i++] = XmStringCreateLocalized(fullname);
642 FindCount = 1;
643
644 rc = DosFindNext(DirHandle, &FindBuffer, sizeof(FindBuffer), &FindCount);
645 #endif
646
647 #ifdef DXD_WIN // ajay
648 FindCount = GetSortedList(mask, dir, list, MAX_DIR_LIST, 0);
649 XtFree(mask);
650 for (i=0; i<FindCount; i++) {
651 names[i] = XmStringCreateLocalized(list[i]);
652 free(list[i]);
653 }
654
655 #endif
656
657 if (!FindCount)
658 names[FindCount++] = XmStringCreateLocalized(" [ ] ");
659
660 XtVaSetValues(w,
661 XmNfileListItems, names,
662 XmNfileListItemCount, FindCount,
663 XmNdirSpec, names[0],
664 XmNlistUpdated, True,
665 NULL);
666
667 while (FindCount > 0)
668 XmStringFree(names[--FindCount]);
669
670 XtFree(dir);
671 }
672
673 extern "C" void NonUnixDirSearchProc(Widget w, XtPointer search_data)
674 {
675 char dirmask[_MAX_PATH];
676 char *list[MAX_DIR_LIST];
677 char fullname[_MAX_PATH];
678 char *dir;
679 XmString names[MAX_DIR_LIST];
680 int i=0;
681 #ifdef os2
682 HDIR DirHandle=1;
683 FILEFINDBUF3 FindBuffer;
684 APIRET rc;
685 #endif
686 #ifdef DXD_WIN
687 long rc;
688 #endif
689 int FindCount = 0;
690
691
692 XmFileSelectionBoxCallbackStruct *cbs =
693 (XmFileSelectionBoxCallbackStruct *) search_data;
694
695 if (!XmStringGetLtoR(cbs->dir, XmFONTLIST_DEFAULT_TAG, &dir))
696 return;
697
698 UNIX2DOSPATH(dir);
699 strcpy(dirmask, dir);
700 strcat(dirmask, "*");
701
702 #ifdef os2
703 rc = DosFindFirst(dirmask, &DirHandle, MUST_HAVE_DIRECTORY | FILE_READONLY, (PVOID) &FindBuffer,
704 sizeof(FindBuffer), &FindCount, FIL_STANDARD);
705
706 while(!rc && i<MAX_DIR_LIST){
707 strcpy(fullname,dir);
708 strcat(fullname,FindBuffer.achName);
709
710 DOS2UNIXPATH(fullname);
711 names[i++] = XmStringCreateLocalized(fullname);
712 FindCount = 1;
713
714 rc = DosFindNext(DirHandle, &FindBuffer, sizeof(FindBuffer), &FindCount);
715 #endif
716
717 #ifdef DXD_WIN // ajay
718 FindCount = GetSortedList(dirmask, dir, list, MAX_DIR_LIST, 1);
719 XtFree(dir);
720 for (i=0; i<FindCount; i++) {
721 names[i] = XmStringCreateLocalized(list[i]);
722 free(list[i]);
723 }
724
725 #endif
726
727 if (!FindCount) {
728 names[FindCount++] = XmStringCreateLocalized("/.");
729 names[FindCount++] = XmStringCreateLocalized("/..");
730 }
731
732 XtVaSetValues(w,
733 XmNdirListItems, names,
734 XmNdirListItemCount, FindCount,
735 XmNlistUpdated, True,
736 XmNdirectoryValid, True,
737 NULL);
738
739 while (FindCount > 0)
740 XmStringFree(names[--FindCount]);
741
742 XtFree(dir);
743 }
744
745
746
747 extern "C" const char *GetNullStr(XmString str)
748 {
749 XmStringContext cxt;
750 char *text, *tag;
751 static char buf[1024];
752 XmStringDirection dir;
753 Boolean sep;
754 int os;
755
756 if (!str) return "";
757 if (!XmStringInitContext (&cxt, str)) {
758 XtWarning ("Can't convert compound string.");
759 return "";
760 }
761 os = 0;
762 while (XmStringGetNextSegment (cxt, &text, &tag, &dir, &sep)) {
763 strcpy (&buf[os], text);
764 os+= strlen(text);
765 if (sep) {
766 buf[os++] = '\n';
767 }
768 // unsure about this line. The motif manual doesn't do this
769 // but purify complains about memory loss
770 if (tag) XtFree(tag);
771 XtFree(text);
772 }
773
774 buf[os] = '\0';
775 ASSERT(os<sizeof(buf));
776 XmStringFreeContext(cxt);
777 return buf;
778 }
779
780 #endif
781
782
783
784
785