root/trunk/txlib/txwstdlg.c

Revision 14, 123.1 kB (checked in by jvw, 2 years ago)

HEX/ASCII (sector) editor control added

Line 
1//
2//                     TxWin, Textmode Windowing Library
3//
4//   Original code Copyright (c) 1995-2005 Fsys Software and Jan van Wijk
5//
6// ==========================================================================
7//
8// This file contains Original Code and/or Modifications of Original Code as
9// defined in and that are subject to the GNU Lesser General Public License.
10// You may not use this file except in compliance with the License.
11// BY USING THIS FILE YOU AGREE TO ALL TERMS AND CONDITIONS OF THE LICENSE.
12// A copy of the License is provided with the Original Code and Modifications,
13// and is also available at http://www.dfsee.com/txwin/lgpl.htm
14//
15// This library is free software; you can redistribute it and/or modify
16// it under the terms of the GNU Lesser General Public License as published
17// by the Free Software Foundation; either version 2.1 of the License,
18// or (at your option) any later version.
19//
20// This library is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23// See the GNU Lesser General Public License for more details.
24//
25// You should have received a copy of the GNU Lesser General Public License
26// along with this library; (lgpl.htm) if not, write to the Free Software
27// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28//
29// Questions on TxWin licensing can be directed to: txwin@fsys.nl
30//
31// ==========================================================================
32//
33// TX standard dialogs
34//
35// Author: J. van Wijk
36//
37// JvW  25-03-2004 Added Linux support
38// JvW  12-09-2003 Added Standard File dialogs
39// JvW  15-08-2003 Added (main) menus, menubar
40// JvW  30-07-2003 Added select-lists, listbox
41// JvW  12-03-2002 Added entryfield, promptbox
42// JvW  16-09-2001 Initial version, messagebox
43
44#include <txlib.h>                              // public interface
45#include <txwpriv.h>                            // txwa anchor interface
46
47#define TXWD_MB_WMIN        42                  // min window width messagebox
48#define TXWD_MB_WDEFAULT    76                  // default window  width
49
50#define TXWD_HELPMBOX       0xffff0100          // base help-id messagebox
51#define TXWD_WID_MBOX       0xff10              // window id messagebox
52#define TXWD_WID_MBVIEW     0xff11              // window id textview
53#define TXWD_WID_MBICON     0xff12              // window id icon static
54                                                // window id for buttons are
55                                                // equal to TXMBID_xxx 1..9
56
57#define TXWD_HELPPBOX       0xffff0200          // base help-id promptbox
58#define TXWD_WID_PBOX       0xff20              // window id promptbox
59#define TXWD_WID_PBVIEW     0xff21              // window id textview
60#define TXWD_WID_PBENTRY    0xff22              // window id entryfield
61
62#define TXWD_HELPLBOX       0xffff0300          // base help-id listbox
63#define TXWD_WID_LBOX       0xff30              // window id promptbox
64#define TXWD_WID_LBLIST     0xff31              // window id listbox
65
66#define TXWD_WID_MBAR       0xff3f              // MenuBar id
67#define TXWD_WID_MENU       0xff40              // MenuBar menu base id
68
69#define TXWD_HELPVIEW       0xffff0500          // base help-id textview
70#define TXWD_WID_VIEW       0xff50              // TextView id
71
72
73#define TXWD_HELPFDLG       0xffff0700          // base help-id file dialog
74
75#define TXFD_WID_DFRAME     0xff60              // window-id dialog frame
76#define TXFD_WID_SFNAME     0xff61              // window-id select-fname
77#define TXFD_WID_VOLUME     0xff62              // window-id volume list
78#define TXFD_WID_CREATE     0xff63              // window-id CREATE button
79#define TXFD_WID_CFPATH     0xff64              // window-id PATH output field
80#define TXFD_WID_DIRECT     0xff65              // window-id directory list
81#define TXFD_WID_FNAMES     0xff66              // window-id filename list
82#define TXFD_WID_ACCEPT     0xff67              // window-id ACCEPT button
83
84#define TXWD_FD_WWIDTH      74                  // default window  width
85
86#define TXWD_FD_MAXWILD     10                  // maximum nr of wildcards
87
88typedef struct txwfdata                         // file dialog private data
89{
90   TXSELIST           *direct;                  // list of directories
91   TXSELIST           *fnames;                  // list of filenames
92   TXLN                wildcard;                // selection wildcard
93} TXWFDATA;                                     // end of struct "txwfdata"
94
95static TXSELIST       *txfd_drivelist = NULL;   // cached list of volumes
96static int             txfd_drive_cnt = 0;      // drives in TxFsVolumes
97
98
99static  char           txwNotReadyMsg[]  = "Not ready, disconnected LAN "
100                                           "or unrecognized filesystem";
101static  char           txwSeparatorLine[] =
102   "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"
103   "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ";
104
105static  TX1K           txwSaveAsPath     = "";
106static  TX1K           txwOpenFilePath   = "";
107static  TX1K           txwSelDirFilePath = "";
108
109static char           *msgboxhelp[] =
110{
111   "#000 Messagebox",
112   "",
113   " A Message box is used to pass a relative small text (the message)",
114   " to you, and let you acknowledge it by pushing a button or use the",
115   " <Esc> key on the keyboard.",
116   "",
117   " Most messageboxes can be moved, resized and minimized/maximized",
118   " For moving, use the <Alt> + 'm' key, and then the arrow keys.",
119   " The <Insert> key toggles between MOVE and SIZE as indicated",
120   " by the text in the status line near the bottom of the screen.",
121   "",
122   " If the box is too small for the text to fit, you can scroll using:",
123   "    Ctrl + Home   Scroll up to first non-empty line in the text",
124   "    Ctrl + End    Scroll down to last line in the text",
125   "    Alt  + . (>)  Scroll message text right by 1 char",
126   "    Alt  + , (<)  Scroll message text left  by 1 char",
127   "    Up   / Down   Scroll message text up / down line by line",
128   "",
129   " Message boxes come in several flavors with the most significant",
130   " difference being the number and kind of push buttons provided.",
131   "",
132   " Possible buttons with their most common meanings are:",
133   "",
134   "   [Ok]        Accept the message, acknowledge it",
135   "   [Cancel]    Don't accept the message, deny it",
136   "   [Yes]       Accept the message, answer Yes to the question",
137   "   [No]        Don't accept the message, answer No to the question",
138   "   [Enter]     Accept the message, acknowledge it",
139   "   [Abort]     Abort the failing action indicated by the message",
140   "   [Retry]     Retry the failed action indicated by the message",
141   "   [Ignore]    Ignore the failed action, and continue",
142   "   [Help]      Give additional help on the content of the message",
143   "",
144   " Pushing one of the buttons using the  <Space bar> or <Enter> key,",
145   " or using the <Esc> key will end the message box display, and pass",
146   " on the associated result to the application.",
147   " The <Esc> key is equivalent to the [No] or [Cancel] buttons.",
148   "",
149   " Help about the message contents and consequences can be called with",
150   " the <F1> function key, or the [Help] button when available.",
151   "",
152   " Once help is displayed, another <F1> will call up the help info",
153   " about the message box itself (this page)",
154   "",
155   NULL
156};
157
158static char           *textviewhelp[] =
159{
160   "#000 Text Viewer",
161   "",
162   " The text viewer window is used to display text lines",
163   "",
164   NULL
165};
166
167static char           *filedlghelp[] =
168{
169   "#000 File Dialog",
170   "",
171   " The file dialog is used to select a file to be used by the",
172   " program for reading (File Open) or writing (File Save As) or",
173   " to select a directory for reading or saving files.",
174   "",
175   " The dialog has an entryfield that can contain a fileselection",
176   " to restrict displayed files (wildcard). On selection of a file",
177   " this field will contain the base-filename for it (no path).",
178   "",
179   " You can retrieve the original value (wildcard) with <F2>.",
180   "",
181   " The path for this filename, and for other filenames displayed",
182   " in the list, is shown just below this entryfield and will be",
183   " updated when changing drives and/or directories.",
184   "",
185   " Then there are three listboxes to select DRIVE, DIRECTORY and",
186   " the actual FILENAME.",
187   "",
188   " The dialog may be enhanced with additional fields and buttons",
189   " called custom 'widgets' to specify more options or values.",
190   " For help on those widgets, use the <F1> help key a 2nd time",
191   "",
192   " The File-dialog can be moved, resized and minimized/maximized",
193   " For moving, use the <Alt> + 'm' key, and then the arrow keys.",
194   " The <Insert> key toggles between MOVE and SIZE as indicated",
195   " by the text in the status line near the bottom of the screen.",
196   "",
197   "",
198   " Combined 'Filename or wildcard' entryfield",
199   " ==========================================",
200   "",
201   " This field my contain a selection wildcard, limiting the files",
202   " displayed in the FILENAME list, or it may contain a complete",
203   " filename (non-wildcard) that represents the selected file.",
204   "",
205   " Using <ENTER> with a complete filename will end the dialog and",
206   " return the selected path and filename to the application.",
207   "",
208   " At any time, for example if a filename (from the filelist) is",
209   " displayed here, you can retrieve the original wildcard string",
210   " with the UP-arrow key. Using <ENTER> on this field will update",
211   " the other fields and lists in the dialog accordingly.",
212   "",
213   " The wildcard-string entered may contain MULTIPLE wildcards",
214   " separated by a ';' character, to allow more complex selections",
215   " to me made. An example would be to display all .CMD and .BAT",
216   " files in the displayed path using the wildcard-string:",
217   "",
218   "                   *.bat;*.cmd",
219   "",
220   " Another example is displaying any .LOG file that has one of,",
221   " three possible fragments in the name:",
222   "",
223   "                   *test*.log;*first*.log;*\\my*.log",
224   "",
225   " Note the leading '*' characters in each, these are REQUIRED as",
226   " the whole path will be considered in the match-process.",
227   "",
228   "",
229   " List of selectable volumes (driveletters)",
230   " =========================================",
231   "",
232   " This is a 'spin-value' list that shows the current volume on",
233   " a single line, and allows selection of others using the <Up>",
234   " and <Down> arrow keys."
235   "",
236   " It contains all the volumes (driveletters) that are available",
237   " to the operating system for accessing regular files.",
238   "",
239   " The list can be expanded to a pop-up by using <Alt> + <Enter>",
240   "",
241   " Selection of a new volume, either by using the <Up> or <Down>",
242   " arrow keys or by using <Enter> on the popup, will result in",
243   " the current PATH being changed to the root-directory on that",
244   " volume and the directory/filename lists being updated as well.",
245   "",
246   "",
247   " 'Make Directory' button and entryfield",
248   " ======================================",
249   "",
250   " The button will present you with a prompt-box entryfield to ",
251   " specify the name of a new directory to be created.",
252   "",
253   " This will usually be a subdirectory for the current PATH used",
254   " in the dialog, but it can also be an absolute location on another",
255   " drive, or more than one level of subdirectories.",
256   "",
257   " Examples:    'newdir'        create directory 'newdir' in PATH",
258   "              'sub\\new'       create directory 'sub'    in PATH",
259   "                              and directory 'new' in this 'sub'",
260   "              'h:\\tmp'        create directory 'tmp' on H: drive",
261   "",
262   " The specified directory or directories will be created on closing",
263   " this prompt-box using <ENTER>, and the default PATH for the File",
264   " dialog will be changed to this new location.",
265   "",
266   "",
267   " List of directories in current PATH",
268   " ===================================",
269   "",
270   " This is a selection list where all subdirectories, and",
271   " the parent directory of the current PATH are shown.",
272   "",
273   " Selection of one of the directories by highlighting it and",
274   " using the <Enter> key results in changing the current PATH",
275   " to that directory and the directory/filename being updated.",
276   "",
277   "",
278   " List of matching files in the current PATH",
279   " ==========================================",
280   "",
281   " This is a selection list of all files in the current PATH that",
282   " match the wildcard specification in the filename field (if any).",
283   "",
284   " Selection of one of the filenames by highlighting it and using",
285   " the <Enter> key results in THAT file being the selected one.",
286   " This will end the dialog and return the selected path and",
287   " filename to the application.",
288   "",
289   "",
290   " [ OK ] button to accept the path",
291   " ================================",
292   "",
293   " The [ OK ] button or the <F4> key will end the dialog with the",
294   " currently displayed full-path (in blue) as the selected path.",
295   "",
296   TXHELPITEM(999,"End of File Dialog help")
297   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
298   NULL
299};
300
301static char           *promptboxhelp[] =
302{
303   "#000 Prompt Box",
304   "",
305   " A Prompt box is used to get a single value from you to be used as",
306   " input to the program. There will be a short message explaining what",
307   " the value is needed for",
308   "",
309   " Prompt boxes may be enhanced with additional fields and buttons",
310   " called custom 'widgets' to specify more options or values.",
311   "",
312   " Most promptboxes can be moved, resized and minimized/maximized",
313   " For moving, use the <Alt> + 'm' key, and then the arrow keys.",
314   " The <Insert> key toggles between MOVE and SIZE as indicated",
315   " by the text in the status line near the bottom of the screen.",
316   "",
317   " Help about the prompted value and consequences can be called with",
318   " the <F1> function key",
319   "",
320   " Once help is displayed, another <F1> will call up the help info",
321   " about the prompt box itself (this page)",
322   "",
323   NULL
324};
325
326
327static char           *stdmsghelp[] =
328{
329   "#000 Standard Message",
330   "",
331   TXHELPITEM(10, "Windows and screen size")
332   "",
333   " When you confirm this message, the size of the text window will be",
334   " changed to a value that is more likely to work comfortably with the",
335   " currently running program",
336   "",
337   " It is presented to you because the program detected that it is",
338   " likely that the text-window currently has vertical scroll-bars.",
339   "",
340   "",
341   "", "", "", "", "", "", "", "", "", "", "", "",
342   "",
343   TXHELPITEM(20, "Critical Error, Retry or Fail")
344   "",
345   " This is a DOS critical error message, meaning it is something the",
346   " operating system itself can't do much about, but maybe you can!",
347   "",
348   " After correcting the problem (or not), you can choose how the",
349   " program should continue processing:",
350   "",
351   "       Retry    Will cause the failing operation to be retried.",
352   "",
353   "       Fail     Will cause the error to be reported to the program",
354   "                itself, allowing it to take appropriate measures.",
355   "",
356   TXHELPITEM(999,"End of Standard Message help")
357   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
358   NULL
359};
360
361
362// Button texts for the MessageBox
363static char txmb_bt_ok[]       = " OK ";
364static char txmb_bt_cancel[]   = "Cancel";
365static char txmb_bt_yes[]      = "Yes";
366static char txmb_bt_no[]       = " No ";
367static char txmb_bt_enter[]    = "Enter";
368static char txmb_bt_abort[]    = "Abort";
369static char txmb_bt_retry[]    = "Retry";
370static char txmb_bt_ignore[]   = "Ignore";
371static char txmb_bt_fail[]     = "Fail";
372static char txmb_bt_help[]     = "Help";
373
374       char txwstd_footer[]    = "F1=Help F4=OK F12=Minimize "
375#ifndef LINUX
376                                 "Alt+m=Move/Size Alt+F10=Maximize"
377#endif
378                                 ;
379       char txwfld_footer[]    = "F1=Help F2=wildcard F4=OK F12=Minimize "
380#ifndef LINUX
381                                 "Alt+m=Move/Size"
382#endif
383                                 ;
384
385// Dialog window procedure, for the MsgBox dialog
386static ULONG txwMsgBoxDlgWinProc                // RET   result
387(
388   TXWHANDLE           hwnd,                    // IN    current window
389   ULONG               msg,                     // IN    message id
390   ULONG               mp1,                     // IN    msg param 1
391   ULONG               mp2                      // IN    msg param 2
392);
393
394
395// Window procedure, for entry-field, includes automatic value-echo
396static ULONG txwPromptDlgWinProc                // RET   result
397(
398   TXWHANDLE           hwnd,                    // IN    current window
399   ULONG               msg,                     // IN    message id
400   ULONG               mp1,                     // IN    msg param 1
401   ULONG               mp2                      // IN    msg param 2
402);
403
404
405// Window procedure, for ListBox popup
406static ULONG txwListDlgWinProc                  // RET   result
407(
408   TXWHANDLE           hwnd,                    // IN    current window
409   ULONG               msg,                     // IN    message id
410   ULONG               mp1,                     // IN    msg param 1
411   ULONG               mp2                      // IN    msg param 2
412);
413
414
415// Window procedure, for a MenuBar Dialog
416static ULONG txwMenuDlgWinProc                  // RET   result
417(
418   TXWHANDLE           hwnd,                    // IN    current window
419   ULONG               msg,                     // IN    message id
420   ULONG               mp1,                     // IN    msg param 1
421   ULONG               mp2                      // IN    msg param 2
422);
423
424
425// Window procedure, for some FileDialog controls
426static ULONG txwSfdControlWinProc               // RET   result
427(
428   TXWHANDLE           hwnd,                    // IN    current window
429   ULONG               msg,                     // IN    message id
430   ULONG               mp1,                     // IN    msg param 1
431   ULONG               mp2                      // IN    msg param 2
432);
433
434/*****************************************************************************/
435// Initialize all standard dialog data structures
436/*****************************************************************************/
437BOOL txwInitStandardDialogs
438(
439   void
440)
441{
442   BOOL                rc = TRUE;               // function return
443
444   ENTER();
445
446   txwInitGenericWidgets();                     // initialize widgets
447
448   txwRegisterHelpText( TXWD_HELPMBOX, "Message box help",  msgboxhelp);
449   txwRegisterHelpText( TXWD_HELPPBOX, "Prompt box help",   promptboxhelp);
450   txwRegisterHelpText( TXWD_HELPVIEW, "Text viewer help",  textviewhelp);
451   txwRegisterHelpText( TXWD_HELPFDLG, "File Dialog help",  filedlghelp);
452   txwRegisterHelpText( TXWD_HELPSMSG, "Standard messages", stdmsghelp);
453
454   if (TxaExeSwitchUnSet('F'))                  // -F- is no-autoFail
455   {
456      TxFsAutoFailCriticalErrors( FALSE);       // allow TXWIN popups ...
457   }
458   BRETURN (rc);
459}                                               // end 'txwInitStandardDialogs'
460/*---------------------------------------------------------------------------*/
461
462
463/*****************************************************************************/
464// Terminate all standard dialog data structures
465/*****************************************************************************/
466void txwTermStandardDialogs
467(
468   void
469)
470{
471   ENTER();
472
473   txSelDestroy( &txfd_drivelist);              // free drives   list
474   txfd_drive_cnt = 0;
475
476   TxFsAutoFailCriticalErrors( TRUE);           // no popups anymore ...
477
478   txwTermGenericWidgets();                     // terminate widgets
479
480   VRETURN();
481}                                               // end 'txwTermStandardDialogs'
482/*---------------------------------------------------------------------------*/
483
484
485/*****************************************************************************/
486// Display standard message-box dialog with text, buttons and help-id
487/*****************************************************************************/
488ULONG txwMessageBox
489(
490   TXWHANDLE           parent,                  // IN    parent window
491   TXWHANDLE           owner,                   // IN    owner  window
492   char               *message,                 // IN    message text
493   char               *title,                   // IN    title for the dialog
494   ULONG               helpid,                  // IN    help on message
495   ULONG               flags                    // IN    specification flags
496)
497{
498   ULONG               rc = NO_ERROR;           // function return
499
500   ENTER();
501   TRACES(("parent:%8.8lx  owner:%8.8lx  title:'%s'\n", parent, owner, title));
502   TRACES(("helpid:%8.8lx = %lu  flags:%8.8lx\n", helpid, helpid, flags));
503
504   if (txwIsWindow( TXHWND_DESKTOP))            // is there a desktop ?
505   {
506      TXRECT           position;                // reference size/position
507      TXWHANDLE        mframe;                  // message-box frame
508      TXWHANDLE        mview;                   // help view text
509      TXWHANDLE        mbut1;                   // button 1
510      TXWHANDLE        mbut2;                   // button 2
511      TXWHANDLE        mbut3;                   // button 3
512      TXWHANDLE        mbut4;                   // button 4
513      TXWINDOW         window;                  // setup window data
514      ULONG            style;
515      char            *tbut1;                   // button texts
516      char            *tbut2;
517      char            *tbut3;
518      char            *tbut4;
519      USHORT           rbut1 = 0;               // button result codes
520      USHORT           rbut2 = 0;
521      USHORT           rbut3 = 0;
522      USHORT           rbut4 = 0;
523      short            phsize;                  // parent window width
524      short            pvsize;                  // parent window height
525      USHORT           focusID;                 // Button to get focus
526      char           **mText;
527      int              lines;                   // nr of lines
528      int              ll;                      // real max line length
529      int              b1 = 0;                  // button-1 left reference
530      int              ww = (strlen( message) < 160) ? TXWD_MB_WMIN
531                                                     : TXWD_MB_WDEFAULT;
532      switch (flags & TXMB_PRIMARYSTYLES)
533      {
534         case TXMB_OKCANCEL:
535            tbut1   = txmb_bt_ok;        rbut1 = TXMBID_OK;
536            tbut3   = txmb_bt_cancel;    rbut3 = TXMBID_CANCEL;
537            focusID = (flags & TXMB_DEFBUTTON2) ? rbut3 : rbut1;
538            break;
539
540         case TXMB_RETRYCANCEL:
541            tbut1   = txmb_bt_retry;     rbut1 = TXMBID_RETRY;
542            tbut3   = txmb_bt_cancel;    rbut3 = TXMBID_CANCEL;
543            focusID = (flags & TXMB_DEFBUTTON2) ? rbut3 : rbut1;
544            break;
545
546         case TXMB_ABORTRETRYIGNORE:
547            tbut1   = txmb_bt_abort;     rbut1 = TXMBID_ABORT;
548            tbut2   = txmb_bt_retry;     rbut2 = TXMBID_RETRY;
549            tbut3   = txmb_bt_ignore;    rbut3 = TXMBID_IGNORE;
550            focusID = (flags & TXMB_DEFBUTTON3) ? rbut3 :
551                      (flags & TXMB_DEFBUTTON2) ? rbut2 : rbut1;
552            break;
553
554         case TXMB_RETRYFAIL:
555            tbut1   = txmb_bt_retry;     rbut1 = TXMBID_RETRY;
556            tbut3   = txmb_bt_fail;      rbut3 = TXMBID_FAIL;
557            focusID =                    rbut3; // fail always default
558            break;
559
560         case TXMB_YESNO:
561            tbut1   = txmb_bt_yes;       rbut1 = TXMBID_YES;
562            tbut3   = txmb_bt_no;        rbut3 = TXMBID_NO;
563            focusID = (flags & TXMB_DEFBUTTON2) ? rbut3 : rbut1;
564            break;
565
566         case TXMB_YESNOCANCEL:
567            tbut1   = txmb_bt_yes;       rbut1 = TXMBID_YES;
568            tbut2   = txmb_bt_no;        rbut2 = TXMBID_NO;
569            tbut3   = txmb_bt_cancel;    rbut3 = TXMBID_CANCEL;
570            focusID = (flags & TXMB_DEFBUTTON3) ? rbut3 :
571                      (flags & TXMB_DEFBUTTON2) ? rbut2 : rbut1;
572            break;
573
574         case TXMB_CANCEL:
575            if (flags & TXMB_HELP)
576            {
577               tbut1 = txmb_bt_cancel;   rbut1 = TXMBID_CANCEL;
578               focusID =                 rbut1;
579            }
580            else
581            {
582               tbut2 = txmb_bt_cancel;   rbut2 = TXMBID_CANCEL;
583               focusID =                 rbut2;
584            }
585            break;
586
587         case TXMB_ENTER:
588            if (flags & TXMB_HELP)
589            {
590               tbut1 = txmb_bt_enter;    rbut1 = TXMBID_ENTER;
591               focusID =                 rbut1;
592            }
593            else
594            {
595               tbut2 = txmb_bt_enter;    rbut2 = TXMBID_ENTER;
596               focusID =                 rbut2;
597            }
598            break;
599
600         case TXMB_ENTERCANCEL:
601            tbut1   = txmb_bt_enter;     rbut1 = TXMBID_ENTER;
602            tbut3   = txmb_bt_cancel;    rbut3 = TXMBID_CANCEL;
603            focusID = (flags & TXMB_DEFBUTTON2) ? rbut3 : rbut1;
604            break;
605
606         case TXMB_OK:
607         default:
608            if (flags & TXMB_HELP)
609            {
610               tbut1   = txmb_bt_ok;     rbut1 = TXMBID_OK;
611               focusID =                 rbut1;
612            }
613            else
614            {
615               tbut2   = txmb_bt_ok;     rbut2 = TXMBID_OK;
616               focusID =                 rbut2;
617            }
618            break;
619      }
620      if (flags & TXMB_HELP)
621      {
622         tbut4      = txmb_bt_help;   rbut4 = TXMBID_HELP;
623         if (ww < TXWD_MB_WDEFAULT)
624         {
625            ww  += 12;
626         }
627      }
628      if (flags & TXMB_ANYICON)
629      {
630         if (ww < TXWD_MB_WDEFAULT)
631         {
632            ww   = TXWD_MB_WDEFAULT;
633         }
634         b1 = 11;                               // 12 positions for icon
635      }
636      else if (ww == TXWD_MB_WDEFAULT)
637      {
638         b1 = 9;                                // center icons in large MB
639      }
640
641      if (rbut2 && !(rbut1 || rbut3 || rbut4))  // center single button-2
642      {
643         b1 = ((ww - strlen(tbut2) -6) /2) -15; // middle, minus fixed offset
644      }
645      TRACES(( "left button pos b1 : %u for ww = %u\n", b1, ww));
646
647      ll    = ww -4;
648      mText = txString2Text( message, &ll, &lines);
649
650      txwQueryWindowRect( parent, FALSE, &position);
651      phsize = position.right;
652      pvsize = position.bottom;
653
654      if (position.left  + ww < phsize)
655      {
656         position.right  = ww;
657         position.left   = phsize - ww;
658         if (flags & TXMB_HCENTER)
659         {
660            position.left /= 2;                 // center horizontally
661         }
662      }
663      if (position.top   + lines + 8 < pvsize)
664      {
665         position.bottom = lines + 8;
666         if (flags & TXMB_VCENTER)              // center in top 60 lines
667         {                                      // 1/4 above, 3/4 below ...
668            position.top += ((min( pvsize, 60) - position.bottom) / 4);
669         }
670      }
671      TRECTA( "pos/size", (&position));
672
673      style = TXWS_DIALOG | TXWS_DISABLED | TXCS_CLOSE_BUTTON;
674      if (flags & TXMB_MOVEABLE)
675      {
676         style |= TXWS_MOVEABLE;                // make frame move/sizeable
677      }
678      txwSetupWindowData(
679         position.top,                          // upper left corner
680         position.left,
681         position.bottom,                       // vertical size
682         position.right,                        // horizontal size
683         style | TXWS_CAST_SHADOW,              // window frame style
684         TXWD_HELPMBOX,                         // messagebox help
685         ' ', ' ', TXWSCHEME_COLORS,
686         title, txwstd_footer,
687         &window);
688      window.st.buf     = NULL;                 // NO artwork attached
689      window.dlgFocusID = focusID;              // Field to get Focus
690      mframe = txwCreateWindow( parent, TXW_CANVAS, 0, 0, &window, NULL);
691
692      style = TXWS_CHILDWINDOW | TXWS_DISABLED;
693      if (flags & TXMB_MOVEABLE)
694      {
695         style |= TXWS_HCHILD_SIZE;             // resize with parent
696         style |= TXWS_VCHILD_SIZE;
697      }
698      txwSetupWindowData(
699         1,                                     // UL corner, line   (relative)
700         (position.right >= ll +2) ? ((position.right -ll -2) / 2) :
701         1,                                     // UL corner, column (relative)
702         position.bottom - 8,                   // vertical size
703         position.right  - 4,                   // horizontal size
704         style,                                 // window frame style
705         helpid,                                // help on the message
706         ' ', ' ', TXWSCHEME_COLORS, "",  "",
707         &window);
708      window.tv.topline = 0;
709      window.tv.leftcol = 0;
710      window.tv.maxtop  = TXW_INVALID;
711      window.tv.maxcol  = TXW_INVALID;
712      window.tv.buf     = mText;
713      mview = txwCreateWindow( mframe, TXW_TEXTVIEW, mframe, 0, &window,
714                               txwDefWindowProc);
715      txwSetWindowUShort( mview,  TXQWS_ID,   TXWD_WID_MBVIEW);
716
717      if (rbut1 != 0)                           // do we have a button 1 ?
718      {
719         style = TXWS_PBUTTON;
720         if (flags & TXMB_MOVEABLE)
721         {
722            style |= TXWS_VCHILD_MOVE;          // move with vertical resize
723         }
724         txwSetupWindowData(
725            position.bottom - 6,                // UL corner, line   (relative)
726            b1 +  1,                            // UL corner, column (relative)
727            3,                                  // vertical size
728            strlen( tbut1) + 4,                 // horizontal size   (auto)
729            style,                              // window frame style
730            helpid,                             // help on the message
731            ' ', ' ', TXWSCHEME_COLORS, "",  "",
732            &window);
733         window.bu.text = tbut1;
734         mbut1 = txwCreateWindow(   mframe, TXW_BUTTON, mframe, 0, &window,
735                                    txwDefWindowProc);
736         txwSetWindowUShort( mbut1, TXQWS_ID, rbut1); // returncode == ID
737      }
738
739      if (rbut2 != 0)                           // do we have a button 2 ?
740      {
741         style = TXWS_PBUTTON;
742         if (flags & TXMB_MOVEABLE)
743         {
744            style |= TXWS_HCHILD2MOVE;          // 1/2 move when parent resizes
745            style |= TXWS_VCHILD_MOVE;          // move with vertical resize
746         }
747         txwSetupWindowData(
748            position.bottom - 6,                // UL corner, line   (relative)
749            b1 + 15,                            // UL corner, column (relative)
750            3,                                  // vertical size
751            strlen( tbut2) + 4,                 // horizontal size   (auto)
752            style,                              // window frame style
753            helpid,