home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c163 / 3.ddi / SCRE_SOU.EXE / G4COMBO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-29  |  16.0 KB  |  490 lines

  1. /* g4combo.c  ComboBox Area Routines  (c)Copyright Sequiter Software Inc., 1991.  All rights reserved. */
  2.  
  3. #include "c4window.h"
  4. #include "e4error.h"
  5.  
  6. #ifdef __TURBOC__
  7.    #pragma hdrstop
  8. #endif
  9.  
  10. int S4FUNCTION g4combo_add( G4COMBO *combo, char *choice, int do_select )
  11. {
  12.    int rc = g4list_add( combo->list, choice, do_select ) ;
  13.    if ( rc < 0 )  return rc ;
  14.    if ( do_select )
  15.       if ( combo->list->select != 0 )
  16.          combo4_setselection( combo->edit.ca.gw.hWindow, w4entry( combo ), 0 ) ;
  17.    return rc ;
  18. }
  19.  
  20. int S4CALL combo4_buttonproc( G4BUTTON *button )
  21. {
  22.    G4COMBO *combo = (G4COMBO *) g4button_data( button ) ;
  23.    W4ENTRY *ew = w4entry( combo ) ;
  24.  
  25.    if ( combo->is_down )
  26.       combo4_process_message( combo, WM_SYSKEYDOWN, VK_UP, 0x20000000L ) ;
  27.    else
  28.       combo4_process_message( combo, WM_SYSKEYDOWN, VK_DOWN, 0x20000000L ) ;
  29.     
  30.    SetFocus( g4handle( &combo->edit ) ) ;
  31.    ew->ControlList.selected = (void *) &combo->edit.ca ;
  32.  
  33.    return 0 ;       /* don't close entry window */
  34. }
  35.  
  36. /* '0' is returned to send message to the G4EDIT proc. */
  37.  
  38. int combo4_process_message( G4COMBO *combo, WORD msg, WORD wParam, LONG lParam )
  39. {
  40.    int index, index2 ;
  41.  
  42.    switch( msg )
  43.    {
  44.       case WM_CHAR:
  45.          if ( combo->edit.isModify == 0 )
  46.          {
  47.             SendMessage( g4handle( combo->list ), WM_CHAR, wParam, lParam ) ;
  48.             return 0 ;
  49.          }
  50.  
  51.       case WM_KEYDOWN:
  52.          if ( combo->edit.Buffer == 0 )
  53.          {
  54.             combo->edit.Buffer = (char *) u4alloc( combo->edit.pResultLen+1 ) ;
  55.             if ( combo->edit.Buffer == 0 )
  56.             {
  57.                e4error( g4cb( combo ), e4memory, (char *) 0 ) ;
  58.                return 1 ;
  59.             }
  60.             combo->edit.Buffer[combo->edit.pResultLen] = 0 ;
  61.          }
  62.  
  63.          index2 = (int) SendMessage( g4handle( combo->list ), LB_GETCURSEL, 0, 0 ) ;
  64.          CallWindowProc( combo->edit.ca.gw.OldWindowProc,
  65.                          g4handle( &combo->edit ), msg, wParam, lParam ) ;
  66.  
  67.          index = (int) SendMessage( g4handle( combo->list ), LB_FINDSTRING,
  68.                   -1, (DWORD) (LPSTR) combo->edit.Buffer ) ;
  69.  
  70.          if ( index < 0 )
  71.             SendMessage( g4handle( combo->list ), LB_SETCURSEL, -1, 0 ) ;
  72.  
  73.      if ( (index2 < 0) && (index >= 0) )
  74.         SendMessage( g4handle( combo->list ), LB_SETCURSEL, index, NULL ) ;
  75.  
  76.          return 1 ;   
  77.  
  78.       case WM_SYSKEYDOWN:
  79.          switch( wParam )
  80.          {
  81.             case VK_DOWN:
  82.                if ( lParam & 0x20000000L )
  83.                {                         
  84.                   G4CONTROL *ca ;
  85.                   int combo_height = combo4_combosize( w4entry( combo )) ;
  86.  
  87.                   /* 'height' of listbox has to be a multiple of tm.tmHeight */
  88.                   TEXTMETRIC tm ;
  89.                   HDC hDC = w4get_dc( g4cb( combo ), g4handle( combo->list )) ;
  90.                   if ( hDC == 0 )  return 0 ;
  91.                   w4get_metrics( hDC, &tm ) ;
  92.                   if ( w4release_dc( g4cb( combo ), g4handle( combo->list ), hDC ) == 0 )  return 0 ;
  93.  
  94.                   if ( combo->is_down == 1 ) return 1 ;
  95.                   if ( combo->isDrop == 1 )
  96.                   {
  97.                      ShowWindow( g4handle( combo->list ), SW_SHOWNORMAL ) ;
  98.                      UpdateWindow( g4handle( combo->list )) ;
  99.                   }
  100.                   combo->is_down = 1 ;
  101.  
  102.                   for ( ca = 0 ; ca = (G4CONTROL *) l4next( &combo->edit.ca.ew->ControlList, ca ) ; )
  103.                   {
  104.                      if ( ca->area_type == c4edit )
  105.                      {
  106.                         G4EDIT *ea = (G4EDIT *) ca->area ;
  107.                         if ( ea->combo != 0 )
  108.                         {
  109.                            G4COMBO *cba = ea->combo ;
  110.                              ValidateRect( g4handle( cba->list ), 0 ) ;
  111.                              ValidateRect( g4handle( &cba->edit ), 0 ) ;
  112.                            if ( cba->button != 0 )
  113.                               ValidateRect( g4handle( cba->button ), 0 ) ;
  114.                         }
  115.                      }
  116.                      ca->nopaint = 1 ;
  117.                      ValidateRect( g4handle( ca ), 0 ) ;
  118.                   }
  119.                   return 1 ;
  120.                }
  121.                else
  122.                {
  123.                   SendMessage( g4handle( combo->list ), WM_KEYDOWN, VK_DOWN, NULL ) ;
  124.                   return 1 ;
  125.                }
  126.  
  127.             case VK_UP:
  128.                if ( lParam & 0x20000000L )
  129.                {
  130.                   combo->is_down = 0 ;
  131.                   if ( combo->isDrop == 1 )
  132.                   {
  133.                      ShowWindow( g4handle( combo->list ), SW_HIDE ) ;
  134.                      UpdateWindow( g4handle( combo->list )) ;
  135. /*****
  136.    (uncomment the following 2 lines for the following effect)
  137.  
  138.    The validation function (if one exists) is called when the combobox is
  139.    closed.  This allows the user to update controls that exist 'under' the
  140.    combobox.  Since the validation is also called when the selection changes,
  141.    the validation could be called twice.
  142. *****/
  143. /*                   if ( ! u4ptr_equal( (void *) 0, (void *) combo->edit.valid ) ) */
  144. /*                      (*combo->edit.valid)( (struct G4EDIT_st *) &combo->edit, combo->edit.valid_data ) ; */
  145.                   }
  146.                   return 1 ;
  147.                }
  148.                break ;
  149.          }
  150.          break ;
  151.    }
  152.    return 0 ;
  153. }
  154.  
  155. /* if 'refresh' = 1, then refresh from original, otherwise do not */
  156.  
  157. void combo4_setselection( HWND hwnd, W4ENTRY *ew, int refresh )
  158. {
  159.    int      id    = GetWindowWord( hwnd, GWW_ID ) ;
  160.    G4EDIT  *ea    = g4lookup_edit( ew, id ) ;
  161.    G4COMBO *combo = (G4COMBO *) ea->combo ;
  162.  
  163.    long index ;
  164.  
  165.    if ( ea->pResultLen <= 0 )  return ;  /* no edit buffer */
  166.    index = SendMessage( g4handle( combo->list ), LB_GETCURSEL, 0, 0 ) ;
  167.  
  168.    if ( index == LB_ERR )
  169.    {
  170.       index++ ;
  171.       SendMessage( g4handle( combo->list ), LB_SETCURSEL, (WORD) index, (DWORD) NULL ) ;
  172.    }
  173.    if ( combo->edit.Buffer != 0 )
  174.       u4free( combo->edit.Buffer ) ;
  175.  
  176.    combo->edit.Buffer = (char *) u4alloc( combo->edit.pResultLen+1 ) ;
  177.    if ( combo->edit.Buffer == 0 )
  178.    {
  179.       e4error( g4cb( combo ), e4memory, (char *) 0 ) ;
  180.       return ;
  181.    }
  182.    memset( combo->edit.Buffer, ' ', combo->edit.pResultLen ) ;
  183.    combo->edit.Buffer[combo->edit.pResultLen] = 0 ;
  184.  
  185.    /* The combobox choices could be longer than the edit buffer */
  186.    {
  187.       char buf[256] ;  memset( buf, ' ', 255 ) ;  buf[255] = 0 ;
  188.       SendMessage( g4handle( combo->list ), LB_GETTEXT, (int) index, (DWORD) buf ) ;
  189.       u4ncpy( ea->Buffer, buf, ea->pResultLen+1 ) ;
  190.    }
  191.  
  192.    if ( ! u4ptr_equal( (void *) 0, (void *) combo->edit.valid ) )
  193.       if ( (*combo->edit.valid)( (struct G4EDIT_st *) &combo->edit, combo->edit.valid_data ) != 0 )
  194.          return ;
  195.  
  196.    InvalidateRect( g4handle( &combo->edit ), 0, 0 ) ;
  197.  
  198.    if ( refresh == 0 )  return ;
  199.  
  200.    if ( combo->edit.data_field != 0 )
  201.    {
  202.       memcpy( combo->edit.Buffer, combo->edit.pResult, combo->edit.pResultLen ) ;
  203.  
  204.       index = SendMessage( g4handle( combo->list ), LB_FINDSTRING, -1, (DWORD) combo->edit.Buffer ) ;
  205.       if ( index == LB_ERR )
  206.          SendMessage( g4handle( combo->list ), LB_SETCURSEL, -1, 0 ) ;
  207.       else
  208.          SendMessage( g4handle( combo->list ), LB_SETCURSEL, (int) index, 0 ) ;
  209.    }
  210. }
  211.  
  212. G4COMBO *S4FUNCTION g4combo( W4ENTRY *ew, int x, int y, int width, int height, char *ptr,
  213.                              unsigned ptr_len, int do_sort )
  214. {
  215.    C4CONTROLITEM control ;
  216.  
  217.    #ifdef S4DEBUG
  218.       if ( ew == 0 )
  219.          e4severe( e4parm, "g4list()", E4_PARM_ZER, (char *) 0 ) ;
  220.    #endif
  221.  
  222.    if ( ew->gw.cw->cb.error_code < 0 )  return 0 ;
  223.  
  224.    control.Id    = entry4_nextid( ew ) ;
  225.    control.Style = ( do_sort == 0 ) ? 0 : CBS_SORT ;
  226.    control.Y     = y ;
  227.    control.X     = x ;
  228.    control.CX    = width ;
  229.    control.CY    = height ;
  230.  
  231.    return combo4_create( ew, &control, ptr, ptr_len, -1, -1 ) ; 
  232. }
  233.  
  234. void S4FUNCTION g4combo_simple( G4COMBO *combo )
  235. {
  236.    int combo_height ;
  237.  
  238.    #ifdef S4DEBUG
  239.       if ( combo == 0 )
  240.          e4severe( e4parm, "g4combo_simple()", E4_PARM_ZER, (char *) 0 ) ;
  241.    #endif
  242.  
  243.    if ( combo->button == 0 )  return ;
  244.    combo->isDrop = 0 ;
  245.  
  246.    DestroyWindow( g4handle( (void *) combo->button ) ) ;
  247.    button4_free( combo->button ) ;
  248.    combo->button = 0 ;
  249.  
  250.    combo->edit.width = combo->width ;
  251.    combo_height = combo4_combosize( w4entry( combo )) ;
  252.  
  253.    ShowWindow( g4handle( combo->list ), SW_SHOWNORMAL ) ;
  254.    UpdateWindow( g4handle( combo->list )) ;
  255. }
  256.  
  257. void combo4_buttondrawbitmap( HDC hdc, HBITMAP hBitmap, short xStart, short yStart )
  258. {
  259.    BITMAP bm ;
  260.    POINT  ptSize, ptOrg ;
  261.  
  262.    HDC hdcMem = CreateCompatibleDC( hdc ) ;
  263.    if ( hdcMem == 0 )
  264.       e4severe( e4result, E4_RESULT_CDC, (char *) 0 ) ;
  265.    SelectObject( hdcMem, hBitmap ) ;
  266.    SetMapMode( hdcMem, GetMapMode( hdc )) ;
  267.  
  268.    GetObject( hBitmap, sizeof( BITMAP ), (LPSTR) &bm ) ;
  269.  
  270.    ptSize.x = bm.bmWidth ;
  271.    ptSize.y = bm.bmHeight ;
  272.    DPtoLP( hdc, &ptSize, 1 ) ;
  273.  
  274.    ptOrg.x = ptOrg.y = 0 ;
  275.    DPtoLP( hdcMem, &ptOrg, 1 ) ;
  276.  
  277.    BitBlt( hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y,
  278.                                                                    SRCCOPY ) ;
  279.    DeleteDC( hdcMem ) ;
  280. }
  281.  
  282. void combo4_buttondraw( LPDRAWITEMSTRUCT draw, W4ENTRY *ew )
  283. {
  284.    RECT        rc;
  285.    HBRUSH hbr;
  286.  
  287.    CopyRect( (LPRECT)&rc, (LPRECT)&draw->rcItem ) ;
  288.  
  289.    hbr = CreateSolidBrush( 0x00FFFFFFL ) ;
  290.    FillRect( draw->hDC, (LPRECT)&rc, hbr ) ;
  291.    DeleteObject( hbr ) ;
  292.  
  293.    combo4_buttondrawbitmap( draw->hDC, ew->gw.cw->combo_arrow, 5, 5 ) ;
  294.  
  295.    hbr = GetStockObject( BLACK_BRUSH ) ;
  296.    FrameRect( draw->hDC, (LPRECT)&rc, hbr ) ;
  297.    DeleteObject( hbr ) ;
  298.  
  299.    hbr = GetStockObject( LTGRAY_BRUSH ) ;
  300.    SelectObject( draw->hDC, hbr ) ;
  301.    ExtFloodFill( draw->hDC, 1, 1, 0x00000000, FLOODFILLBORDER ) ;
  302.    DeleteObject( hbr ) ;
  303. }
  304.  
  305. int combo4_combosize( W4ENTRY *ew )
  306. {
  307.    TEXTMETRIC tm ;
  308.  
  309.    HDC hDC = w4get_dc( w4cb( ew ), ew->gw.hWindow ) ;
  310.    if ( hDC == 0 )  return 0 ;
  311.  
  312.    w4get_metrics( hDC, &tm ) ;
  313.    if ( w4release_dc( w4cb( ew ), ew->gw.hWindow, hDC ) == 0 )  return 0 ;
  314.  
  315.    return ( tm.tmHeight + tm.tmInternalLeading ) ;
  316. }
  317.  
  318. G4COMBO *combo4_create( W4ENTRY *ew, C4CONTROLITEM *control, char *ptr,
  319.                         unsigned ptr_len, int low, int high )
  320. {
  321.    G4COMBO *combo ;
  322.    int combo_height = combo4_combosize( ew ) ;
  323.  
  324.    if ( ew->gw.cw->cb.error_code < 0 )  return 0 ;
  325.  
  326.    if ( combo_height == 0 )  return 0 ;
  327.    combo = combo4_makecombo( control, low, high, combo_height ) ;
  328.    if ( combo == 0 )  return 0 ;
  329.    if ( combo4_makeedit( ew, combo, control, ptr, ptr_len ) < 0 )
  330.    {
  331.       u4free( combo ) ;
  332.       return 0 ;
  333.    }
  334.    if ( combo4_makelist( ew, combo, control->Style ) < 0 )
  335.    {
  336.       if ( combo->edit.Pict != 0 )  u4free( combo->edit.Pict ) ;
  337.       u4free( combo ) ;
  338.       return 0 ;
  339.    }
  340.    if ( combo4_makebutton( ew, combo, combo_height ) < 0 )
  341.    {
  342.       u4free( combo->list ) ;
  343.       if ( combo->edit.Pict != 0 )  u4free( combo->edit.Pict ) ;
  344.       u4free( combo ) ;
  345.       return 0 ;
  346.    }
  347.    l4add( &ew->ControlList, (void *) &combo->edit.ca ) ;
  348.  
  349.    return combo ;
  350. }
  351.  
  352. G4COMBO *combo4_makecombo ( C4CONTROLITEM *control, int low, int high, int combo_height )
  353. {
  354.    G4COMBO *cba = (G4COMBO *) u4alloc( sizeof(G4COMBO) ) ;
  355.    if ( cba == 0 )
  356.       e4severe( e4memory, (char *) 0 ) ;
  357.  
  358.    cba->is_down = 0 ;
  359.    cba->isDrop  = 1 ;
  360.  
  361.    if ( low < 0 )
  362.    {
  363.       cba->x       = control->X  ;
  364.       cba->y       = control->Y  ;
  365.       cba->width   = control->CX ;
  366.       cba->height  = control->CY ;
  367.    }
  368.    else
  369.    {
  370.       cba->x       = (control->X  * low )/4 ;
  371.       cba->y       = (control->Y  * high)/8 ;
  372.       cba->width   = (control->CX * low )/4 ;
  373.       cba->height  = (control->CY * high)/8 ;
  374.    }
  375.    return cba ;
  376. }
  377.  
  378. int combo4_makelist( W4ENTRY *ew, G4COMBO *cba, LONG style )  /* use list4_create ??? */
  379. {
  380.    int combo_height = combo4_combosize( w4entry( cba )) ;
  381.  
  382.    cba->list = (G4LIST *) u4alloc( sizeof( G4LIST )) ;
  383.    if ( cba->list == 0 )
  384.       return e4error( g4cb( cba ), e4memory, (char *) 0 ) ;
  385.  
  386.    control4_construct( &cba->list->ca, ew ) ;
  387.    cba->list->ca.gw.Id = entry4_nextid( ew ) ;
  388.  
  389.    cba->list->ca.gw.Style = LBS_NOTIFY | WS_VSCROLL | WS_BORDER | WS_CHILD ;
  390.    if ( CBS_SORT == (style & CBS_SORT) )
  391.       cba->list->ca.gw.Style |= LBS_SORT ;
  392.  
  393.    cba->list->ca.gw.hWindow = w4create_window( "ListBox", 0,
  394.                                        cba->list->ca.gw.Style,
  395.                                        cba->x, cba->y+combo_height,
  396.                        cba->width, cba->height-combo_height,
  397.                                        w4handle( ew ), cba->list->ca.gw.Id,
  398.                                        w4hInst( ew ), 0 ) ;
  399.  
  400.    cba->list->ca.gw.OldWindowProc = (FARPROC) GetWindowLong( g4handle( cba->list ),
  401.                                                       GWL_WNDPROC ) ;
  402.    SetWindowLong( g4handle( cba->list ), GWL_WNDPROC, (LONG) ew->gw.cw->list4_proc ) ;
  403.             
  404.    cba->list->ca.hParent   = w4handle( ew ) ;
  405.    cba->list->ca.ew        = ew ;
  406.    cba->list->ca.gw.cw     = ew->gw.cw ;
  407.    cba->list->ca.area_type = c4list ;
  408.    cba->list->ca.area      = (void *) cba->list ;
  409.  
  410.    cba->list->combo = (struct G4COMBO_st *) cba ;
  411.  
  412.    return 0 ;
  413. }
  414.  
  415. int combo4_makebutton( W4ENTRY *ew, G4COMBO *cba, int combo_height ) /* use button4_create ??? */
  416. {
  417.    cba->button = (G4BUTTON *) u4alloc( sizeof(G4BUTTON) ) ;
  418.    if ( cba->button == 0 )
  419.       return e4error( g4cb( cba ), e4memory, (char *) 0 ) ;
  420.  
  421.    button4_construct( cba->button, ew ) ;
  422.    cba->button->ca.gw.Id = entry4_nextid( ew ) ;
  423.    cba->button->ca.gw.Style = WS_TABSTOP | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ;
  424.  
  425.    cba->button->ca.gw.hWindow = w4create_window( "Button", "C",
  426.                                       cba->button->ca.gw.Style | BS_OWNERDRAW,
  427.                                       cba->x+cba->width-GetSystemMetrics( SM_CXVSCROLL), cba->y, GetSystemMetrics( SM_CXVSCROLL ), combo_height,
  428.                                       w4handle( ew ), cba->button->ca.gw.Id,
  429.                                       w4hInst( ew ), 0 ) ;
  430.  
  431.    cba->button->ca.gw.OldWindowProc = (FARPROC) GetWindowLong( g4handle( cba->button ),
  432.                                                       GWL_WNDPROC ) ;
  433.    SetWindowLong( g4handle( cba->button ), GWL_WNDPROC, (LONG) ew->gw.cw->button4_proc ) ;
  434.             
  435.    cba->button->ca.hParent = w4handle( ew ) ;
  436.    cba->button->ca.ew      = ew ;
  437.    cba->button->ca.gw.cw   = ew->gw.cw ;
  438.  
  439.    cba->button->routine = (S4BUTTON *) combo4_buttonproc ;
  440.    cba->button->routine_data = (void *) cba ;
  441.  
  442.    cba->button->combo = (struct G4COMBO_st *) cba ;
  443.  
  444.    return 0 ;
  445. }
  446.  
  447. int combo4_makeedit( W4ENTRY *ew, G4COMBO *cba, C4CONTROLITEM *control,
  448.                      char *ptr, unsigned ptr_len ) 
  449. {
  450.    edit4_make( ew, &cba->edit ) ;
  451.    if ( edit4_make2( ew, &cba->edit, cba->x, cba->y, 0, t4str, -1, -1, control->Id ) < 0 )
  452.    {
  453.       if ( cba->edit.Pict != 0 )  u4free( cba->edit.Pict ) ;
  454.       return -1 ;
  455.    }
  456.  
  457.    g4width( &cba->edit, cba->width-GetSystemMetrics( SM_CXVSCROLL )) ;
  458.    g4set_buffer( &cba->edit, ptr, ptr_len ) ;
  459.    cba->edit.combo = (struct G4COMBO_st *) cba ;
  460.  
  461.    cba->edit.ca.gw.OldWindowProc = (FARPROC) GetWindowLong( g4handle( &cba->edit ),
  462.                                                       GWL_WNDPROC ) ;
  463.    SetWindowLong( g4handle( &cba->edit ), GWL_WNDPROC, (LONG) ew->gw.cw->combo4_proc ) ;
  464.  
  465.    return 0 ;
  466. }
  467.  
  468. int S4FUNCTION g4combo_reset( G4COMBO *cba )
  469. {
  470.    int len ;
  471.  
  472.    if ( cba->edit.Buffer != 0 )
  473.    {
  474.       len = lstrlen( cba->edit.Buffer ) ;
  475.       if ( len > 0 )  memset( cba->edit.Buffer, ' ', len ) ;
  476.       InvalidateRect( g4handle( &cba->edit ), 0, 0 ) ;
  477.    }
  478.    return g4list_reset( cba->list ) ;
  479. }
  480.  
  481. int S4FUNCTION g4combo_ptr_save( G4COMBO *cba, void *ptr )
  482. {
  483.    return g4list_ptr_save( cba->list, ptr ) ;
  484. }
  485.  
  486. void * S4FUNCTION g4combo_ptr( G4COMBO *cba )
  487. {
  488.    return g4list_ptr( cba->list ) ;
  489. }
  490.