home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / tui160 / picklist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-02  |  28.4 KB  |  722 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /* PICKLIST.C                                                               */
  4. /*                                                                          */
  5. /* This is a demonstration of how to use UltraWin and InTUItion to perform  */
  6. /* some slick pick lists and browsers with full keyboard and mouse          */
  7. /* capability!  This file was created with a tab size of 2, and is heavily  */
  8. /* commented.                                                               */
  9. /*                                                                          */
  10. /*                                                         Boyd Gafford     */
  11. /*                                                         EnQue Software   */
  12. /*                                                         03/16/92         */
  13. /*                                                                          */
  14. /****************************************************************************/
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. #include "t.h"                          /* include the main TUI header file */
  18. #include "picklist.def"                 /* include the TUICP define file    */
  19.  
  20. #define SH_TOP_LEFT     0               /* used by shadow window functions  */
  21. #define SH_TOP_RIGHT    1
  22. #define SH_BOTTOM_RIGHT 2
  23. #define SH_BOTTOM_LEFT  3
  24.  
  25. /*----------------------- global program variables -------------------------*/
  26. TUI     Demo_tui;
  27.  
  28. char    *Text_strs[] =
  29. {"                 EnQue Offers FREE Programming Tools for C",
  30. "",
  31. "    EnQue Software has released a new version of its UltraWin text",
  32. " windowing library.  Key features of UltraWin 2.60 are unlimited overlapping",
  33. " windows, background printing, PC timer control, mouse and graphic support,",
  34. " and enhanced data entry capabilities.  Also included are a hypertext help",
  35. " engine and an EGA/VGA font editor.",
  36. "",
  37. "    Also released is InTUItion 1.60, a textual user-interface library that",
  38. " includes an interface construction program that allows UltraWin users to",
  39. " interactively create dialog boxes, menus, pick lists, forms and more using",
  40. " a mouse.  Source code can be automatically generated to perform processing",
  41. " on each item, saving hours of tedious hand coding and debugging.",
  42. "",
  43. "    The UltraWin and InTUItion tools and small model libraries are available",
  44. " FREE from most major online services, the EnQue BBS, or by sending $2.00 for",
  45. " shipping and handling to EnQue Software.  Complete source code, large model",
  46. " libraries and printed manual can be obtained from EnQue for $99.95 for",
  47. " UltraWin and $199.90 for both UltraWin and InTUItion.  Free upgrades and",
  48. " technical support are available through the EnQue BBS.",
  49. "",
  50. "    Requires either Microsoft C or Quick C, Turbo C/C++, Borland C/C++,",
  51. " Watcom C32 or Zortech C/C++.  For more information please contact:",
  52. "",
  53. "    EnQue Software",
  54. "    Route 1, Box 116C",
  55. "    Pleasant Hill, MO  64080",
  56. "    Voice/Fax (816) 987-2515",
  57. "    EnQue BBS (816) 353-0991"
  58. };
  59.  
  60. char    *Pick_strs[] =
  61. {
  62. " Brock, Eddie",
  63. " Forbush, Irving",
  64. " Gafford, Boyd ",
  65. " Huck, Kevin",
  66. " Jameson, J.J ",
  67. " Lee, Stan",
  68. " Leeds Brant, Betty",
  69. " Leeds, Ned",
  70. " Lubinsky, Nathan",
  71. " Osborne, Harry",
  72. " Parker, Ben",
  73. " Parker, May",
  74. " Parker, Peter",
  75. " Robinson, Robbie",
  76. " Stacy, Gwen",
  77. " Thompson, Flash",
  78. " Watson, Anna",
  79. " Watson Parker, Mary Jane",
  80. " Whitman, Deborah"
  81. };
  82.  
  83. /*------------------------------ prototypes --------------------------------*/
  84. void interact_menu( TUI *tuip, int dlg_inx );
  85. void pick_sel( TUI *tuip, int dlg_inx );
  86. void output_str( int x, int y, int w, int first_inx, char *str, WINDOW *wnp );
  87. void browse_strings( char **strs, int num );
  88. int pick_strings( char **strs, int num );
  89. void msg_line( char *msg );
  90. void deselect_and_draw( TUI *tuip, int inx );
  91. void shadow_window( WINDOW *wnp, int type, int w, int h, int att );
  92. void unshadow_window( WINDOW *wnp );
  93.  
  94. /*********/
  95. /* ~main */
  96. /*       ********************************************************************/
  97. /****************************************************************************/
  98. void main(void)
  99. {
  100.   WINDOW  *desk_wnp;
  101.   int     i, c;
  102.  
  103.   load_tui(&Demo_tui, "PICKLIST.TUI");
  104.   init_tui(&Demo_tui);
  105.   init_clock(0x3333);                           /* use 91 ticks/sec.  This  */
  106.                                                 /* is required for tone and */
  107.                                                 /* for more precise timing! */
  108.   m_hide();
  109.   c = (Demo_tui.back_att & 0xF0) >> 4;          /* get background color     */
  110.   desk_wnp = Demo_tui.back_wnp;                 /* get desktop window ptr   */
  111.   desk_wnp->scroll = OFF;                       /* turn off desktop scroll  */
  112.   for (i=0; i<182; i++)                         /* do a little background   */
  113.   {                                             /* to show off the shadow   */
  114.     wn_color((i % 8) + 8, c, desk_wnp);
  115.     wn_st("InTUItion  ", desk_wnp);
  116.   }
  117.   desk_wnp->att = Demo_tui.back_att;            /* restore desktop att      */
  118.   wn_color(BLACK, BLUE, desk_wnp);
  119.   m_show();
  120.  
  121.   interact_menu(&Demo_tui, MENU_DIALOG);        /* do the main menu!        */
  122.  
  123.   end_clock();                                  /* and the cleanup stuff    */
  124.   end_tui(&Demo_tui);
  125.   free_tui(&Demo_tui);
  126.   exit(0);
  127. }
  128. /*** end of main ***/
  129.  
  130. /******************/
  131. /* ~interact_menu */
  132. /*                ***********************************************************/
  133. /* This function pulls up the main TUI menu, and allows the user to select  */
  134. /* the demonstration for each function.  Notice how both the internal       */
  135. /* transfer mechanism (recursion of do_dialog) and the "do it yourself"     */
  136. /* transfer is done.                                                        */
  137. /****************************************************************************/
  138. void interact_menu( TUI *tuip, int dlg_inx )
  139. {
  140.   WINDOW  *wnp;
  141.   int     ret_inx, inx, end_flag = OFF;
  142.   char    disp_str[81];
  143.  
  144.   draw_dialog(tuip, dlg_inx);                     /* show the dialog        */
  145.   wnp = get_dlg_wnp(tuip, dlg_inx);               /* get the window pointer */
  146.   m_hide();
  147.   shadow_window(wnp, SH_BOTTOM_RIGHT, 2, 1, DARKGRAY);
  148.   m_show();
  149.   while (!end_flag)
  150.   {
  151.     msg_line("Select from the menu above");
  152.     ret_inx = do_dialog(tuip, dlg_inx, DO_NORMAL);
  153.     switch( ret_inx )
  154.     {
  155.       /*---------------- these are from the internal xfer ------------------*/
  156.       /*-- each button in the transfer dialog was set to exit all levels ---*/
  157.       case SEL_1: tone(256,  20); break;
  158.       case SEL_2: tone(512,  20); break;
  159.       case SEL_3: tone(768,  20); break;
  160.       case SEL_4: tone(1024, 20); break;
  161.       case SEL_5: tone(1280, 20); break;
  162.       case SEL_6: tone(1536, 20); break;
  163.       case SEL_7: tone(1792, 20); break;
  164.       case SEL_8: tone(2048, 20); break;
  165.  
  166.       /*-------------------- and do same thing ourselves -------------------*/
  167.       case NORMAL_PICK_LIST:
  168.         msg_line("Select from the menu at right");
  169.         pick_sel(tuip, PICK_LIST_DLG);
  170.         break;
  171.  
  172.       /*--------------------- browse the set of strings --------------------*/
  173.       case STRING_BROWSER:
  174.         msg_line("Use the cursor keys or sliders to scroll around the text");
  175.         browse_strings(Text_strs, 29);
  176.         break;
  177.  
  178.       /*--------------------- do a scrolling pick list! --------------------*/
  179.       case SCROLLING_PICK_LIST:
  180.         msg_line("Select a name from the list");
  181.         if ( (inx = pick_strings(Pick_strs, 19)) != -1)
  182.         {
  183.           tone(2048, 10);
  184.           sprintf(disp_str, "You chose%s!", Pick_strs[inx]);
  185.           msg_line(disp_str);
  186.           /* Uw_timers[0] = 91;
  187.           while (Uw_timers[0] > 0) {} */
  188.           wait_ticks(18L);
  189.         }
  190.         break;
  191.  
  192.       /*--------------------- the quit button was chosen -------------------*/
  193.       case QUIT:
  194.         end_flag = ON;
  195.         break;
  196.     }
  197.     deselect_and_draw(tuip, ret_inx);
  198.   }
  199.   m_hide();
  200.   unshadow_window(wnp);
  201.   m_show();
  202.   erase_dialog(tuip, dlg_inx);
  203. }
  204. /*** end of interact_menu ***/
  205.  
  206. /*************/
  207. /* ~pick_sel */
  208. /*           ****************************************************************/
  209. /* This is the equivalent of doing the transfer pick list ourselves!  Note  */
  210. /* that since this is a function, and not an internal recursive transfer,   */
  211. /* we have full control of what we do WHEN we want to do it!  That means we */
  212. /* can use the new shadow_window function do make things look 3-D.          */
  213. /****************************************************************************/
  214. void pick_sel( TUI *tuip, int dlg_inx )
  215. {
  216.   WINDOW  *wnp;
  217.   int     ret_inx, end_flag = OFF, att = DARKGRAY;
  218.  
  219.   draw_dialog(tuip, dlg_inx);                     /* show the dialog        */
  220.   wnp = get_dlg_wnp(tuip, dlg_inx);               /* get the window pointer */
  221.   m_hide();
  222.   shadow_window(wnp, SH_BOTTOM_RIGHT, 2, 1, att); /* and shadow it!         */
  223.   m_show();
  224.   while (!end_flag)
  225.   {
  226.     ret_inx = do_dialog(tuip, dlg_inx, DO_NORMAL);
  227.     switch( ret_inx )
  228.     {
  229.       /*---------------- ESC pressed or clicked off dialog -----------------*/
  230.       case NO_SELECTION:
  231.         end_flag = ON;
  232.         break;
  233.  
  234.       /*------------------ selections 1-8 just do a tone -------------------*/
  235.       case SEL_1: tone(256,  20), end_flag = ON; break;
  236.       case SEL_2: tone(512,  20), end_flag = ON; break;
  237.       case SEL_3: tone(768,  20), end_flag = ON; break;
  238.       case SEL_4: tone(1024, 20), end_flag = ON; break;
  239.       case SEL_5: tone(1280, 20), end_flag = ON; break;
  240.       case SEL_6: tone(1536, 20), end_flag = ON; break;
  241.       case SEL_7: tone(1792, 20), end_flag = ON; break;
  242.       case SEL_8: tone(2048, 20), end_flag = ON; break;
  243.     }
  244.     deselect_and_draw(tuip, ret_inx);
  245.   }
  246.   m_hide();
  247.   unshadow_window(wnp);
  248.   m_show();
  249.   erase_dialog(tuip, dlg_inx);
  250. }
  251. /*** end of pick_sel ***/
  252.  
  253. /***************/
  254. /* ~output_str */
  255. /*             **************************************************************/
  256. /* This function takes a string, and outputs it to the window, space padded */
  257. /* out to the width passed, if necessary.  if the string is too long for    */
  258. /* the width passed, then it is truncated!  This is a simple routine that   */
  259. /* is used by pick_strings and browse_strings to output each entry to the   */
  260. /* window passed by pointer.  A handy function to have around.              */
  261. /****************************************************************************/
  262. void output_str( int x, int y, int w, int first_inx, char *str, WINDOW *wnp )
  263. {
  264.   int   len = strlen(str);
  265.  
  266.   mv_cs(x, y, wnp);
  267.   if (first_inx >= len)
  268.     wn_qch(w, ' ', wnp);
  269.   else
  270.   {
  271.     len = strlen(&str[first_inx]);
  272.     if (len < w)
  273.       wn_st(&str[first_inx], wnp), wn_qch(w - len, ' ', wnp);
  274.     else
  275.       wn_st_qty(&str[first_inx], w, wnp);
  276.   }
  277. }
  278. /*** end of output_str ***/
  279.  
  280. /*******************/
  281. /* ~browse_strings */
  282. /*                 **********************************************************/
  283. /* Take the array of string pointers and the number of strings, and allow   */
  284. /* the user to browse through using either the keypad or slide bars.  This  */
  285. /* is a simple "text file viewer", and adapts to the size of the box in the */
  286. /* dialog.  To give a bigger view area, just size the display box with the  */
  287. /* TUICP.  You can also move buttons and sliders around without affecting   */
  288. /* this function -- it is all transparent to the code!                      */
  289. /****************************************************************************/
  290. void browse_strings( char **strs, int num )
  291. {
  292.   TUI     *tuip = &Demo_tui;
  293.   WINDOW  *wnp;
  294.   long    tics;
  295.   int     dlg_inx = BROWSER_DLG, ret_inx, end_flag = OFF;
  296.   int     i, max_len, max_x, max_y, x_off = 0, y_off = 0, disp_flag = ON,
  297.           x = get_item_x(tuip, BROWSER_BOX) - 1,
  298.           y = get_item_y(tuip, BROWSER_BOX) - 1,
  299.           w = get_item_w(tuip, BROWSER_BOX),
  300.           h = get_item_h(tuip, BROWSER_BOX),
  301.           att = get_box_att(tuip, BROWSER_BOX),
  302.           num_shown = min(num, h);
  303.  
  304.   max_len = 0;                                    /* find longest length    */
  305.   for (i=0; i<num; i++)                           /* for all strings        */
  306.     if ((int) strlen(strs[i]) > max_len)
  307.       max_len = (int) strlen(strs[i]);
  308.  
  309.   max_x = max(max_len - w, 0);                    /* find maximum x offset  */
  310.   max_y = max(num - h, 0);                        /* find maximum y offset  */
  311.  
  312.  
  313.   set_slider(tuip, BROWSER_HSLIDER,               /* set slider positions   */
  314.     (long) x_off, (long) w, (long) (max_x + 1));
  315.   set_slider(tuip, BROWSER_VSLIDER,
  316.     (long) y_off, (long) h, (long) (max_y + 1));
  317.   draw_dialog(tuip, dlg_inx);
  318.   wnp = get_dlg_wnp(tuip, dlg_inx);               /* get the window pointer */
  319.   m_hide();
  320.   shadow_window(wnp, SH_BOTTOM_RIGHT, 2, 1, DARKGRAY);
  321.   m_show();
  322.   while (!end_flag)
  323.   {
  324.  
  325.     if (disp_flag)                                /* time to display!       */
  326.     {
  327.       switch(disp_flag)                           /* do appropriate slider  */
  328.       {
  329.         case 1:
  330.           set_slider(tuip, BROWSER_HSLIDER,
  331.             (long) x_off, (long) w, (long) (max_x + 1));
  332.           draw_item(tuip, BROWSER_HSLIDER);
  333.           break;
  334.         case 2:
  335.           set_slider(tuip, BROWSER_VSLIDER,
  336.             (long) y_off, (long) h, (long) (max_y + 1));
  337.           draw_item(tuip, BROWSER_VSLIDER);
  338.           break;
  339.       }
  340.       push(wnp->att);                             /* save the window att    */
  341.       wnp->att = att;                             /* use box color itself!  */
  342.       m_hide();                                   /* hide for uwin output   */
  343.       for (i=0; i<num_shown; i++)                 /* loop through the list  */
  344.         output_str(x, y + i, w, x_off,            /* and display the string */
  345.                    strs[i + y_off], wnp);
  346.       m_show();                                   /* show after uwin output */
  347.       pop(wnp->att);                              /* restore the window att */
  348.       disp_flag = OFF;
  349.     }
  350.  
  351.     ret_inx = do_dialog(tuip, dlg_inx, DO_RETURN_EVENT | DO_RETURN_CMD );
  352.  
  353.     switch( ret_inx )
  354.     {
  355.       /*---------------- ESC pressed or clicked off dialog -----------------*/
  356.       case NO_SELECTION:
  357.       case BROWSER_CANCEL:
  358.         end_flag = ON;
  359.         break;
  360.  
  361.      /*---------------------- an event not processable --------------------*/
  362.       case EVENT_RETURNED:
  363.         if (!Event.is_mouse)
  364.         switch( Event.key )
  365.         {
  366.           case KEY_UP:                            /* up one line            */
  367.             if (y_off > 0)
  368.               y_off--, disp_flag = 2;
  369.             break;
  370.           case KEY_DN:                            /* down one line          */
  371.             if (y_off < max_y)
  372.               y_off++, disp_flag = 2;
  373.             break;
  374.           case KEY_PGUP:                          /* up one page            */
  375.             y_off -= h, disp_flag = 2;
  376.             if (y_off < 0)
  377.               y_off = 0;
  378.             break;
  379.           case KEY_PGDN:                          /* down one page          */
  380.             y_off += h, disp_flag = 2;
  381.             if (y_off > max_y)
  382.               y_off = max_y;
  383.             break;
  384.           case KEY_HOME:                          /* to top of list         */
  385.             y_off = 0, disp_flag = 2;
  386.             break;
  387.           case KEY_END:                           /* to bottom of list      */
  388.             y_off = max_y, disp_flag = 2;
  389.             break;
  390.           case KEY_LEFT:                          /* left one character     */
  391.             if (x_off > 0)
  392.               x_off--, disp_flag = 1;
  393.             break;
  394.           case KEY_RIGHT:                         /* right one character    */
  395.             if (x_off < max_x)
  396.               x_off++, disp_flag = 1;
  397.             break;
  398.         }
  399.         break;
  400.  
  401.       case BROWSER_HSLIDER:
  402.         tics = Tics;                              /* just a 4/91 sec delay  */
  403.         while (Tics - tics < 4L) {}
  404.         x_off = (int) get_sldr_pos(tuip, BROWSER_HSLIDER);
  405.         disp_flag = 1;
  406.         break;
  407.  
  408.       case BROWSER_VSLIDER:
  409.         tics = Tics;                              /* just a 4/91 sec delay  */
  410.         while (Tics - tics < 4L) {}
  411.         y_off = (int) get_sldr_pos(tuip, BROWSER_VSLIDER);
  412.         disp_flag = 2;
  413.         break;
  414.  
  415.       case BROWSER_OK:
  416.         end_flag = ON;
  417.         break;
  418.  
  419.     }
  420.     deselect_and_draw(tuip, ret_inx);
  421.   }
  422.   m_hide();
  423.   unshadow_window(wnp);
  424.   m_show();
  425.   erase_dialog(tuip, dlg_inx);
  426. }
  427. /*** end of browse_strings ***/
  428.  
  429. /*****************/
  430. /* ~pick_strings */
  431. /*               ************************************************************/
  432. /* Take the array of string pointers, and allow the user to select from     */
  433. /* them using the dialog we designed with the TUICP.  Please note that the  */
  434. /* function will return 0 to num - 1 if the string was selected, or a -1 if */
  435. /* no string was selected.  You may edit the actual dialog with the TUICP,  */
  436. /* and this routine will adapt to the size of the box for the strings, as   */
  437. /* well as the number of strings shown.  It's all automatic!  Feel free to  */
  438. /* use this routine in your own programs for situations where the user must */
  439. /* choose from an extensive list of items.                                  */
  440. /****************************************************************************/
  441. int pick_strings( char **strs, int num )
  442. {
  443.   TUI     *tuip = &Demo_tui;
  444.   WINDOW  *wnp;
  445.   long    tics, last_tics = Tics;
  446.   int     dlg_inx = SCROLL_PICK_LIST_DLG, ret_inx, end_flag = OFF;
  447.   int     i, last = num - 1, csr = 0, offset = 0, disp_flag = ON,
  448.           x = get_item_x(tuip, PICK_LIST_BOX) - 1,
  449.           y = get_item_y(tuip, PICK_LIST_BOX) - 1,
  450.           w = get_item_w(tuip, PICK_LIST_BOX),
  451.           h = get_item_h(tuip, PICK_LIST_BOX),
  452.           att = get_box_att(tuip, PICK_LIST_BOX),
  453.           num_shown = min(num, h);
  454.  
  455.   set_slider(tuip, PICK_LIST_SLIDER,              /* set slider position    */
  456.     (long) csr, (long) h, (long) num);
  457.   draw_dialog(tuip, dlg_inx);
  458.   wnp = get_dlg_wnp(tuip, dlg_inx);               /* get the window pointer */
  459.   m_hide();
  460.   shadow_window(wnp, SH_BOTTOM_RIGHT, 2, 1, DARKGRAY);
  461.   m_show();
  462.   while (!end_flag)
  463.   {
  464.     if (disp_flag)                                /* time to display!       */
  465.     {
  466.       if (csr < offset)                           /* validate index vars    */
  467.         offset = csr;
  468.       if (offset < 0)
  469.         offset = 0;
  470.       if (offset < (csr - h + 1))
  471.         offset = csr - h + 1;
  472.  
  473.       set_slider(tuip, PICK_LIST_SLIDER,          /* set and draw slider    */
  474.         (long) csr, (long) h, (long) num);
  475.       draw_item(tuip, PICK_LIST_SLIDER);
  476.  
  477.       push(wnp->att);                             /* save the window att    */
  478.       m_hide();                                   /* hide for uwin output   */
  479.       for (i=0; i<num_shown; i++)                 /* loop through the list  */
  480.       {
  481.         if ( (offset + i) == csr )                /* set appropriate att    */
  482.           wn_color(WHITE, BLACK, wnp);
  483.         else
  484.           wn_att(att, wnp);
  485.         output_str(x, y + i, w, 0, strs[i + offset], wnp);
  486.       }
  487.       m_show();                                   /* show after uwin output */
  488.       pop(wnp->att);                              /* restore the window att */
  489.       disp_flag = OFF;
  490.     }
  491.  
  492.     ret_inx = do_dialog(tuip, dlg_inx, DO_RETURN_EVENT | DO_RETURN_CMD );
  493.  
  494.     switch( ret_inx )
  495.     {
  496.       /*---------------- ESC pressed or clicked off dialog -----------------*/
  497.       /*-------------------- or Cancel button pressed ----------------------*/
  498.       case NO_SELECTION:
  499.       case PICK_LIST_CANCEL:
  500.         csr = -1, end_flag = ON;
  501.         break;
  502.  
  503.      /*---------------------- an event passed back to us -------------------*/
  504.       case EVENT_RETURNED:
  505.         if (!Event.is_mouse)
  506.           switch( Event.key )
  507.         {
  508.           case KEY_HOME:                          /* to start of list       */
  509.             csr = offset = 0, disp_flag = ON;
  510.             break;
  511.           case KEY_END:                           /* to the end of the list */
  512.             csr = last, disp_flag = ON;
  513.             break;
  514.           case KEY_PGUP:                          /* up one page            */
  515.             csr -= h;
  516.             if (csr < 0)
  517.               csr = 0;
  518.             disp_flag = ON;
  519.             break;
  520.           case KEY_PGDN:                          /* down one page          */
  521.             csr += h;
  522.             if (csr > last)
  523.               csr = last;
  524.             disp_flag = ON;
  525.             break;
  526.           case KEY_UP:                            /* up one entry           */
  527.             if (csr > 0)
  528.               csr--, disp_flag = ON;
  529.             break;
  530.           case KEY_DN:                            /* down one entry         */
  531.             if (csr < last)
  532.               csr++, disp_flag = ON;
  533.             break;
  534.           case KEY_ENTER:
  535.             end_flag = ON;
  536.             break;
  537.         }
  538.         break;
  539.  
  540.      /*--------------------------- the slider used -------------------------*/
  541.       case PICK_LIST_SLIDER:
  542.         tics = Tics;                              /* just a 4/91 sec delay  */
  543.         while (Tics - tics < 4L) {}
  544.         csr = (int) get_sldr_pos(tuip, PICK_LIST_SLIDER);
  545.         disp_flag = ON;
  546.         break;
  547.  
  548.      /*-------------------- mouse clicked inside the box -------------------*/
  549.       case PICK_LIST_BOX:
  550.         disp_flag = ON;
  551.         csr = offset + (Event.m_y - y - wnp->pane.y_min - 1);
  552.         if (csr > last)
  553.           csr = last;
  554.         if( (Tics - last_tics) < 20L )            /* a double click?        */
  555.           end_flag = ON;
  556.         last_tics = Tics;
  557.         break;
  558.  
  559.      /*----------------------- the ok button was presed --------------------*/
  560.       case PICK_LIST_OK:
  561.         end_flag = ON;
  562.         break;
  563.     }
  564.     deselect_and_draw(tuip, ret_inx);
  565.   }
  566.   m_hide();
  567.   unshadow_window(wnp);
  568.   m_show();
  569.   erase_dialog(tuip, dlg_inx);
  570.   return(csr);
  571. }
  572. /*** end of pick_strings ***/
  573.  
  574. /*************/
  575. /* ~msg_line */
  576. /*           ****************************************************************/
  577. /* Display the message at the last line on the screen.                      */
  578. /****************************************************************************/
  579. void msg_line( char *msg )
  580. {
  581.   WINDOW *wnp = Demo_tui.back_wnp;
  582.  
  583.   push(wnp->att);
  584.   wn_color(BLACK, LIGHTGRAY, wnp);
  585.   mv_cs(0, V_rows - 1, wnp);
  586.   wn_claol(wnp);
  587.   wn_plst(CENTERED, V_rows - 1, msg, wnp);
  588.   pop(wnp->att);
  589. }
  590. /*** end of msg_line ***/
  591.  
  592. /**********************/
  593. /* ~deselect_and_draw */
  594. /*                    *******************************************************/
  595. /* Take the object indexed into the tui array by inx, deselect it, and draw */
  596. /* it.  This "turns off" buttons when they are returned from do_dialog      */
  597. /****************************************************************************/
  598. void deselect_and_draw( TUI *tuip, int inx )
  599. {
  600.   if ( is_valid_inx(tuip, inx) )
  601.     switch( get_item_type(tuip, inx) )
  602.     {
  603.       case T_BUTTON: case T_ICON:
  604.         deselect(tuip, inx);
  605.         draw_item(tuip, inx);
  606.         break;
  607.     }
  608. }
  609. /*** end of deselect_and_draw ***/
  610.  
  611. /******************/
  612. /* ~shadow_window */
  613. /*                ***********************************************************/
  614. /* This routine takes the window passed by pointer and shadows it.  It does */
  615. /* this by creating sub windows using the usr_ptr member of the window      */
  616. /* structure.                                                               */
  617. /*                                                                          */
  618. /* The contents under these sub windows are read off the screen and put     */
  619. /* inside the windows.  The attribute is then changed and the window is     */
  620. /* placed on the screen, giving the illusion of a shadow.                   */
  621. /*                                                                          */
  622. /* You may pass this routine a width, height and attribute (DARKGRAY on     */
  623. /* BLACK with a width of 2 and height of 1 usually looks nice).             */
  624. /* You may also pass a type, which is a number from 0-3 (see #defines) that */
  625. /* indicates the direction the shadow falls.                                */
  626. /*                                                                          */
  627. /* The main thing to remember is be SURE that you call the unshadow_window  */
  628. /* function BEFORE you destroy the window, or else you will have heap       */
  629. /* problems.                                                                */
  630. /****************************************************************************/
  631. void shadow_window( WINDOW *wnp, int type, int w, int h, int att )
  632. {
  633.   WINDOW  *wnp1, *wnp2;                         /* shadow window pointers   */
  634.   int     x1 = wnp->pane.x_min;                 /* get the screen coords    */
  635.   int     y1 = wnp->pane.y_min;
  636.   int     x2 = wnp->pane.x_max;
  637.   int     y2 = wnp->pane.y_max;
  638.   int     win1_x1, win1_y1, win1_x2, win1_y2;
  639.   int     win2_x1, win2_y1, win2_x2, win2_y2;
  640.   int     i;
  641.   uchar   *dest;
  642.  
  643.   if (wnp->usr_ptr == NULL)
  644.   {
  645.     switch(type)
  646.     {
  647.       case SH_TOP_LEFT:
  648.         win1_x1 = x1 - w, win1_y1 = y1 - h;     /* left side of window      */
  649.         win1_x2 = x1 - 1, win1_y2 = y2 - h;
  650.         win2_x1 = x1    , win2_y1 = y1 - h;     /* top side of window       */
  651.         win2_x2 = x2 - w, win2_y2 = y1 - 1;
  652.         break;
  653.       case SH_TOP_RIGHT:
  654.         win1_x1 = x2 + 1, win1_y1 = y1 - h;     /* right side of window     */
  655.         win1_x2 = x2 + w, win1_y2 = y2 - h;
  656.         win2_x1 = x1 + w, win2_y1 = y1 - h;     /* top side of window       */
  657.         win2_x2 = x2    , win2_y2 = y1 - 1;
  658.         break;
  659.       case SH_BOTTOM_LEFT:
  660.         win1_x1 = x1 - w, win1_y1 = y1 + h;     /* left side of window      */
  661.         win1_x2 = x1 - 1, win1_y2 = y2 + h;
  662.         win2_x1 = x1    , win2_y1 = y2 + 1;     /* bottom side of window    */
  663.         win2_x2 = x2 - w, win2_y2 = y2 + h;
  664.         break;
  665.       default:
  666.         win1_x1 = x2 + 1, win1_y1 = y1 + h;     /* right side of window     */
  667.         win1_x2 = x2 + w, win1_y2 = y2 + h;
  668.         win2_x1 = x1 + w, win2_y1 = y2 + 1;     /* bottom side of window    */
  669.         win2_x2 = x2    , win2_y2 = y2 + h;
  670.         break;
  671.     }
  672.     wnp->usr_ptr = calloc(1, sizeof(WINDOW));   /* alloc/create first win   */
  673.     wn_create(win1_x1, win1_y1, win1_x2, win1_y2,
  674.               NO_BDR, WN_POPUP,
  675.               (WINDOW *) wnp->usr_ptr);
  676.     wnp1 = (WINDOW *) wnp->usr_ptr;
  677.     wn_read(wnp1);
  678.     dest = wnp1->buff + 1;                      /* set to DARKGRAY on BLACK */
  679.     for (i=0; i<(wnp1->cols * wnp1->rows); i++)
  680.       *dest = att, dest += 2;
  681.  
  682.     wnp1->usr_ptr = calloc(1, sizeof(WINDOW));  /* alloc/create second win  */
  683.     wn_create(win2_x1, win2_y1, win2_x2, win2_y2,
  684.               NO_BDR, WN_POPUP,
  685.               (WINDOW *) wnp1->usr_ptr);
  686.     wnp2 = (WINDOW *) wnp1->usr_ptr;
  687.     wn_read(wnp2);
  688.     dest = wnp2->buff + 1;                      /* set to DARKGRAY on BLACK */
  689.     for (i=0; i<(wnp2->cols * wnp2->rows); i++)
  690.       *dest = att, dest += 2;
  691.  
  692.     wn_save(wnp1), wn_rfsh(wnp1);               /* do the wn_set equivalent */
  693.     wn_save(wnp2), wn_rfsh(wnp2);
  694.   }
  695. }
  696. /*** end of shadow_window ***/
  697.  
  698. /********************/
  699. /* ~unshadow_window */
  700. /*                  *********************************************************/
  701. /*  This is the complement to shadow_window.  You MUST call this function   */
  702. /* before you destroy the window that has been shadowed or you will have    */
  703. /* severe problems.  If you don't it will have the same effect as not       */
  704. /* calling wn_destroy on a created window.  Your computer will lockup!      */
  705. /****************************************************************************/
  706. void unshadow_window( WINDOW *wnp )
  707. {
  708.   WINDOW  *wnp1, *wnp2;                         /* shadow window pointers   */
  709.  
  710.   if (wnp->usr_ptr)                             /* does it have a shadow?   */
  711.   {
  712.     wnp1 = (WINDOW *) wnp->usr_ptr;             /* get the window pointers  */
  713.     wnp2 = (WINDOW *) wnp1->usr_ptr;
  714.     wn_destroy(wnp2), wn_destroy(wnp1);
  715.     free(wnp2), free(wnp1);                     /* and free the structure   */
  716.     wnp->usr_ptr = NULL;
  717.   }
  718. }
  719. /*** end of unshadow_window ***/
  720.  
  721. /*** END OF FILE ***/
  722.