Page 1 of 1

Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 7:56 am
by Max HK

I am using FWH 19.12.

I found that in GET field and it is Unicode, the characters cannot be highlighted by SHIFT+arrowkeys, only by mouse selection.
If the field is ANSI, highlight is OK.
Have it be solved in new FWH version?

In new version sample programs, is there a program like YUNUS.PRG but using MariaDB?
Is there a sample program to explain all the power of Xbrowse (eg. different sorting seq, searching by value, save JPG to database, drop files, etc.)?

Thanks.


Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 11:27 am
by Antonio Linares

Dear Max,

Lets migrate yunus.prg to use MariaDB:

  1. We install and execute xampp, then we start Apache and MySQL. Then using the internet browser
    we go to localhost/phpmyadmin. We manually create a fwh database and create a user. In our example
    we use fivetec1_antonio as the user name.

  2. We migrate the DBFs to MariaDB using modified samples\maria06.prg:

Modified maria06.prg

Code: Select all | Expand

#include "FiveWin.ch"

REQUEST DBFCDX
REQUEST HB_LANG_ES
REQUEST HB_CODEPAGE_ESWIN

//----------------------------------------------------------------------------//

function Main()

   local oCn, oRs
   local cLog  := cFileSetExt( ExeName(), "log" )

   FErase( cLog )

   RDDSETDEFAULT( "DBFCDX" )
   SET DELETED ON
   SET DATE ITALIAN
   SET CENTURY ON

   HB_CDPSELECT("ESWIN")
   HB_LangSelect( "ES" )

   FW_SetUnicode( .f. )

   oCn := maria_Connect( "localhost", "fwh", "fivetec1_antonio", "1234" )  

   ocn:lLogErr := .t.

   ocn:ImportFromDbf( "invoices.dbf",,,,,,"utf8_spanish2_ci" )

   oRs   := oCn:RowSet( "invoices" )
   XBROWSER oRs FASTEDIT AUTOSORT

   oCn:Close()

   if File( cLog )
      WinExec( "notepad.exe " + cLog )
   endif

return nil

We repeat the process for items.dbf, invitems.dbf and clients2.dbf.

if everything worked as expected then we can see our new MariaDB tables in database fwh from localhost/phpmyadmin


Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 11:32 am
by Antonio Linares

Next we modify yunus.prg function OpenDataBases() this way:

Code: Select all | Expand

static function OpenDataBases()  

   local oCn := maria_Connect( "localhost", "fwh", "fivetec1_antonio", "1234" )  
     
if oCn == nil
MsgStop( "Error connecting to the DataBase" )
return nil
endif
return oCn

Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 12:18 pm
by Antonio Linares

Here you have an initial version of yunusm.prg. Copy yunus.rc to yunusm.rc.

You can use items and clients by now. We are working to complete invoices.

yunusm.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "easyrep.ch"

REQUEST DBFCDX

static oWndMain, oWndInvoices, oWndClients, oWndItems
static aBlankItem
static cItemFlds  := "INVNUM,SERIAL,ITEMCODE,ITEMNAME,QUANTITY,UNIT,PRICE,DISCOUNT,RECNO()"
static nTaxRate   := 0.0
static oCn

//----------------------------------------------------------------------------//

function Main()

   local oBrush, oFont

   OpenDataBases()

   DEFINE BRUSH oBrush RESOURCE "background"
   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-12

//   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE WINDOW oWndMain TITLE "Invoicing" MDI MENU BuildMenu() VSCROLL HSCROLL BRUSH oBrush
   oWndMain:SetFont( oFont )

   BuildMainBar()

   DEFINE MSGBAR PROMPT "Invoicing app" ;
      OF oWndMain 2007 KEYBOARD DATE

   ACTIVATE WINDOW oWndMain MAXIMIZED

   RELEASE BRUSH oBrush

return nil

//----------------------------------------------------------------------------//

INIT PROCEDURE inv_init

   SET DATE BRITISH
   SET CENTURY ON
   SET EPOCH TO ( YEAR( DATE() ) - 50 )

   RDDSETDEFAULT( "DBFCDX" )
   SET DELETED ON

   SetGetColorFocus()

return

//----------------------------------------------------------------------------//

static function BuildMainBar()

   local oBar

   DEFINE BUTTONBAR oBar OF oWndMain 2007 SIZE 70, 60 //70

   DEFINE BUTTON OF oBar PROMPT "Invoices" RESOURCE "code" ;
      ACTION Invoices()

   DEFINE BUTTON OF oBar PROMPT "Clients" RESOURCE "clients" ;
      ACTION Clients()

   DEFINE BUTTON OF oBar PROMPT "Items" RESOURCE "relation" ;
      ACTION Items()

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End()

return nil

//----------------------------------------------------------------------------//

static function BuildMenu()

   local oMenu

   MENU oMenu

  MENUITEM "Tasks"
  MENU
     MENUITEM "Invoices" ACTION Invoices()
     //MENUITEM "Invoices items" ACTION ( "invitems" )->( XBrowse() )
     MENUITEM "Clients"  ACTION Clients()
     MENUITEM "Items"    ACTION Items()
     SEPARATOR
     MENUITEM "Exit" ACTION oWndMain:End()
  ENDMENU

  oMenu:AddMDI()
  oMenu:AddHelp( "Invoicing app", "(c) FiveTech Software" )

   ENDMENU

return oMenu

//----------------------------------------------------------------------------//

static function Clients()

   local oBrw, cClrBack, cAlias, oRs
   local oBar, oMsgBar, oMsgDeleted

   if oWndClients == nil
      oRs = oCn:RowSet( "SELECT * FROM clients2 ORDER BY code" )

  DEFINE WINDOW oWndClients MDICHILD OF oWndMain TITLE "Clients"

  @ 2, 0 XBROWSE oBrw OF oWndClients LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs NOBORDER

  oBar  := BrwBtnBar( @oBrw, oWndClients )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION oBrw:Report( "Clients report",, .F.)

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndClients:End()

  cAlias = Alias()

  BrwColors( oBrw )
  // BrwRecSel( oBrw, "RECNO" )

  oBrw:bEdit  := { |oRec| EditClients( oRec ) }

  oBrw:CreateFromCode()
  oBrw:SetFocus()
  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }

  oWndClients:oClient = oBrw
  oWndClients:oControl = oBrw

  DEFINE MSGBAR oMsgBar OF oWndClients 2007

  ACTIVATE WINDOW oWndClients MAXIMIZED ;
     VALID ( oWndClients := nil, .T. )
   else
      oWndClients:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function Items()

   local oBrw, cClrBack
   local oBar, oMsgBar, oMsgDeleted, oRs

   if oWndItems == nil
      oRs = oCn:RowSet( "SELECT * FROM items ORDER BY code" )

  DEFINE WINDOW oWndItems MDICHILD OF oWndMain TITLE "Items"

  @ 2, 0 XBROWSE oBrw OF oWndItems LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs NOBORDER

  oBar  := BrwBtnBar( @oBrw, oWndItems )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION oBrw:Report( "Items report",, .F.)

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndItems:End()
  BrwColors( oBrw )
  // BrwRecSel( oBrw, "RECNO" )

  oBrw:bEdit  := { |oRec| EditItems( oRec ) }

  oBrw:CreateFromCode()
  oBrw:SetFocus()
  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }

  oWndItems:oClient = oBrw
  oWndItems:oControl = oBrw

  DEFINE MSGBAR oMsgBar OF oWndItems 2007

  ACTIVATE WINDOW oWndItems MAXIMIZED ;
     VALID ( oWndItems := nil, .T. )
   else
      oWndItems:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function Invoices()

   local oBrw, oChild, cClrBack, cCol
   local oBar, oMsgBar, oMsgDeleted, oRs1, oRs2

   if oWndClients == nil
      Clients()
   endif

   if oWndItems == nil
      Items()
   endif

   if oWndInvoices == nil
      oRs1 = oCn:RowSet( "SELECT * FROM invoices ORDER BY code" )
      oRs2 = oCn:RowSet( "SELECT * FROM invitems ORDER BY itemcode" )

  DEFINE WINDOW oWndInvoices MDICHILD OF oWndMain TITLE "Invoices"

  @ 60, 0 XBROWSE oBrw SIZE 0,200 PIXEL OF oWndInvoices LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs1 NOBORDER FOOTERS

  oBar  := BrwBtnBar( @oBrw, oWndInvoices )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION ViewInvoice( oBrw )

  DEFINE BUTTON OF oBar PROMPT "EasyReport" RESOURCE "report" ;
     ACTION ViewInvoiceER( oBrw )

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndInvoices:End()

  DEFINE MSGBAR oMsgBar OF oWndInvoices 2007

  BrwColors( oBrw )
  BrwRecSel( oBrw, "RECNO" )

  for each cCol in { "Amount", "Tax", "Total" }
     oBrw:oCol( cCol ):nFooterType  := AGGR_SUM
  next

  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }
  oBrw:bEdit = { | oRec | EditInvoice( oRec ) }
  oBrw:MakeTotals()
  oBrw:CreateFromCode()
  oBrw:SetFocus()

  oWndInvoices:oControl = oBrw

  @ oBar:nHeight + 200,0 XBROWSE oChild SIZE 0,-oMsgBar:nHeight PIXEL OF oWndInvoices ;
     DATASOURCE oRs2 ;
     COLUMNS "ItemCode", "ItemName", "Quantity", "Unit", "Price", ;
             "ROUND(QUANTITY*PRICE,0)", "DISCOUNT","ROUND(QUANTITY*PRICE,0)-DISCOUNT" ;
     HEADERS "ItmCode", nil, nil, nil, nil, "Amount", "Discount", "Net Amount" ;
     LINES NOBORDER FOOTERS

  BrwColors( oChild )
  // BrwRecSel( oChild, "KEY" )

  for each cCol in { "Amount", "Discount", "Net Amount" }
     WITH OBJECT oChild:oCol( cCol )
        :nFooterType   := AGGR_SUM
     END
  next
  oChild:MakeTotals()
  oChild:CreateFromCode()

  oBrw:bChange   := { || oChild:Refresh(), oChild:MakeTotals(), oChild:GoTop() }

  oWndInvoices:bResized := < ||
     local oRect    := oWndInvoices:GetCliRect()
     oBrw:nHeight   := ( oRect:nHeight - oBar:nHeight - oMsgBar:nHeight ) * 0.6
     oChild:nTop    := oBrw:nTop + oBrw:nHeight
     return nil
     >

  oWndInvoices:bPostEnd   := { || oWndInvoices := nil }

  ACTIVATE WINDOW oWndInvoices MAXIMIZED

   else
      oWndInvoices:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function EditInvoice( oRec )

   local lNew     := ( oRec:RecNo == 0 )
   local oDlg, oBrush, oFont, oBold, oLarge
   local oBrw, cCol, bInit, oBtn
   local aItems
   local oGetClient, cClient, bCliInit
   local nHt      := Int( ScreenHeight() * 0.8 )
   local nWd      := 1100
   local lSave    := .f.

   if lNew
      oRec:Date      := Date()
      oRec:TaxRate   := nTaxRate
      aItems         := { AClone( aBlankItem ) }
   else
      aItems         := IIT->( FW_DbfToArray( cItemFlds, { || IIT->INVNUM == oRec:InvNum } ) )
   endif

   DEFINE BRUSH oBrush RESOURCE "PAPER"
   DEFINE FONT oLarge NAME "VERDANA" SIZE 0,-30 BOLD
   DEFINE FONT oFont NAME  "TAHOMA"  SIZE 0,-15
   DEFINE FONT oBold NAME  "TAHOMA"  SIZE 0,-15 BOLD

   DEFINE DIALOG oDlg SIZE nWd, nHt PIXEL FONT oFont TRUEPIXEL ;
      TITLE If( lNew, "NEW ", "EDIT " ) + "INVOICE" TRANSPARENT ;
      BRUSH oBrush

//   @  20, 40 SAY "INVOICE" SIZE 260,36 PIXEL OF oDlg FONT oLarge ;
   @  20, nWd/2-100 SAY "INVOICE" SIZE 200,36 PIXEL OF oDlg FONT oLarge CENTER

   @ 020, nWd - 190 GET oRec:InvNum PICTURE "@!" SIZE 150,26 PIXEL OF oDlg ;
      VALID ! ( Empty( oRec:InvNum ) .or. INVOICES->( Duplicate( oRec:InvNum, "INVNUM", oRec:RecNo ) ) )

   @ 050, nWd - 190 GET oRec:Date   SIZE 150,26 PIXEL OF oDlg RIGHT ;
                  ACTION oRec:Date := Min( MsgDate( oRec:Date ), Date() )

   @  80-60, 40 SAY "Client:" SIZE 100,24 PIXEL OF oDlg

   @  80-60,150 GET oGetClient VAR oRec:Code SIZE 150,26 PIXEL OF oDlg ;
         ACTION ( PopupBrowse( "CLIENTS", oGetClient ), ;
                  ReadClientInfo( oRec, oDlg ) ) ;
         VALID ( ReadClientInfo( oRec, oDlg ) )

   @ 125-60, 60 SAY oRec:Client SIZE 200,24 PIXEL OF oDlg FONT oBold UPDATE
   @ 150-60, 60 SAY oRec:Address SIZE 200, 60 PIXEL OF oDlg UPDATE

   @ 180-60,310 SAY "Text :" SIZE 100,24 PIXEL OF oDlg
   @ 204-60,310 GET oRec:Details SIZE nWd-310-40,26 PIXEL OF oDlg UPDATE

   @ 240-60,040 XBROWSE oBrw SIZE -40,-150+45 PIXEL OF oDlg ;
      DATASOURCE aItems ;
      COLUMNS 3,4,5,6,7,8 ;
      HEADERS "ITEM", "DETAILS", "QTY", "UNIT","PRICE","DISCOUNT" ;
      PICTURES "@!", nil, "9999.999", nil, "999.99", "999,999,999" ;
      COLSIZES nil, 30 ;
      CELL LINES NOBORDER FASTEDIT FOOTERS

   ADD TO oBrw AT 6 HEADER "AMOUNT" DATA ROUND( oBrw:aRow[5] * oBrw:aRow[7], 0 ) ;
      PICTURE "999,999,999"

   ADD TO oBrw HEADER "NET" DATA ROUND( oBrw:aRow[5] * oBrw:aRow[7] - oBrw:aRow[ 8 ], 0 ) ;
      PICTURE "999,999,999"

   for each cCol in { "amount", "discount", "net" }
      WITH OBJECT oBrw:oCol( cCol )
         :nFooterType   := AGGR_SUM
      END
   next

   for each cCol in { "qty", "price", "discount" }
      WITH OBJECT oBrw:oCol( cCol )
         :nEditType     := EDIT_GET
         :bEditValid    := { |o| o:VarGet() >= 0 }
         :bOnChange     := { || oBrw:MakeTotals( { "amount", "net" } ), oBrw:RefreshFooters(), oDlg:Update() }
      END
   next

   for each cCol in { "details", "unit", "amount", "net" }
      oBrw:oCol( cCol ):bClrStd  := { || { CLR_BLACK, RGB( 240, 240, 240 ) } }
   next

   // AutoAppendCode
   WITH OBJECT oBrw
      :AddVar( "AAPPEND", nil )
      :bClrStd    := { || If( oBrw:aRow == oBrw:aAppend, { CLR_BLACK, CLR_YELLOW }, { CLR_BLACK, oBrw:nClrPane } ) }

  :bChange    := { || If( oBrw:nArrayAt < oBrw:nLen, CheckAppendRow( oBrw ), nil ) }

  :bPastEof   := { || If( oBrw:aAppend != nil .and. Empty( oBrw:aAppend[ 3 ] ), nil, ;
           ( AAdd( oBrw:aArrayData, oBrw:aAppend := AClone( aBlankItem ) ), ;
             oBrw:GoBottom(), oBrw:GoLeftMost(), oBrw:RefreshCurrent(), ;
             oBrw:MakeTotals(), oBrw:Refresh() ) ) }

  :bKeyDown   := { |k| If( k == VK_DELETE, ( oBrw:aAppend := nil, oBrw:Delete(), 0 ), nil ) }

   END

   WITH OBJECT oBrw:aCols[ 1 ]
      :nEditType     = EDIT_BUTTON
      :bEditBlock    = { | nRow, nCol, oCol, nKey | TableLookUp( nRow, nCol, oCol, nKey, "ITEMS" ) }
      :bOnChange     = { || oBrw:aAppend := nil, ReadItemInfo( oBrw:aRow, oBrw ), oBrw:RefreshCurrent(), ;
                            oBrw:MakeTotals(), oBrw:RefreshFooters(), oDlg:Update() }
   END

   WITH OBJECT oBrw
      :lFlatStyle    := .t.
      :nStretchCol   := 2
      :lHScroll      := .f.
      :bOnRefresh    := { || oDlg:Update() }
      //
      BrwRecSel( oBrw, "KEYNO" )
      //
      :MakeTotals()
      :CreateFromCode()
   END

   @ nHt - 139 + 45, nWd - 380 SAY "TAX @" ;
      SIZE 80,24 PIXEL OF oDlg RIGHT

   @ nHt - 140 + 45, nWd - 280 GET oRec:TaxRate PICTURE "99.99 %" ;
      SIZE 100,26 PIXEL OF oDlg RIGHT ;
      VALID ( If( oRec:TaxRate >= 0, ( oDlg:Update(), .t. ), .f. ) )

   @ nHT - 139 + 45, nWd - 170 SAY ;
      ( oRec:Tax := ROUND( oBrw:Net:nTotal * oRec:TaxRate / 100, 0 ) ) ;
      PICTURE "999,999,999" SIZE 105,24 PIXEL OF oDlg UPDATE RIGHT

   @ nHt - 105 + 45, nWd - 270 SAY "TOTAL" SIZE 80, 24 PIXEL OF oDlg RIGHT

   @ nHt - 105 + 45, nWd - 170 SAY ;
      ( oRec:Total := oBrw:Net:nTotal + oRec:Tax ) ;
      PICTURE "999,999,999" SIZE 105, 24 PIXEL OF oDlg UPDATE RIGHT

/*
   @ nHt - 60, nWd - 260 BTNBMP PROMPT "Save"  SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION ( lSave := .t., oDlg:End() )

   @ nHt - 60, nWd - 140 BTNBMP oBtn PROMPT "Cancel" SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION oDlg:End()
   oBtn:lCancel   := .t.
*/
   @ nHt - 60, 040 BTNBMP PROMPT "Save"  SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION ( lSave := .t., oDlg:End() )

   @ nHt - 60, 160 BTNBMP oBtn PROMPT "Cancel" SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION oDlg:End()
   oBtn:lCancel   := .t.



   ACTIVATE DIALOG oDlg CENTERED ;
      ON PAINT (  oDlg:Box( 110-60, 40, 230-60, 300 ), ;
                  oDlg:Line( nHt - 112 + 45, nWd - 170, nHt - 112 + 45, nWd - 55 ), ;
                  oDlg:Line( nHt -  78 + 45, nWd - 170, nHt -  78 + 45, nWd - 55 ), ;
                  oDlg:Line( nHt -  75 + 45, nWd - 170, nHt -  75 + 45, nWd - 55 )  )

   if lSave
      CheckAppendRow( oBrw )
      if Empty( aItems ) .or. Empty( oRec:InvNum ) .or. Empty( oRec:Code ) .or. oRec:Total <= 0
      else

     oRec:Amount    := oBrw:Net:nTotal

     if ! Empty( oBrw:aDeleted )
        AEval( oBrw:aDeleted, { |a| a[ 9 ] := -a[ 9 ] } )
        IIT->( FW_SaveArrayToDBF( cItemFlds, oBrw:aDeleted ) )
     endif
     AEval( aItems, { |a| a[ 1 ] := oRec:InvNum } )
     AEval( aItems, { |a,i| a[ 2 ] := i } )
     IIT->( FW_SaveArrayToDBF( cItemFlds, aItems ) )
     oRec:Save()
     WITH OBJECT oRec:oBrw
        :MakeTotals()
        :RefreshFooters()
        Eval( :bChange, oRec:oBrw )
     END
  endif

   endif

   RELEASE FONT oFont, oLarge
   RELEASE BRUSH oBrush

return nil

//----------------------------------------------------------------------------//

static function CheckAppendRow( oBrw, aAppend )

   if Empty( ATail( oBrw:aArrayData )[ 3 ] )
      ASize( oBrw:aArrayData, oBrw:nLen - 1 )
      oBrw:aAppend  := nil
      oBrw:Refresh()
   endif

return nil

//----------------------------------------------------------------------------//

static function ReadClientInfo( oRec, oDlg )

   local nSaveRec := CLIENTS->( RECNO() )
   local lValid   := .f.

   if CLIENTS->( DBSEEK( oRec:Code ) )
      oRec:Client    := TRIM( CLIENTS->FIRST ) + " " + TRIM( CLIENTS->LAST )
      oRec:Address   := CLIENTS->( PickAddress() )
      lValid         := .t.
   endif
   CLIENTS->( DBGOTO( nSaveRec ) )

   if oDlg != nil
      oDlg:Update()
   endif

return lValid

//----------------------------------------------------------------------------//

static function PickAddress()

   local aRet  := {}

   if ! Empty( FIELD->ADDRESS1 ); AAdd( aRet, TRIM( FIELD->ADDRESS1 ) ); endif
   if ! Empty( FIELD->ADDRESS2 ); AAdd( aRet, TRIM( FIELD->ADDRESS2 ) ); endif
   if ! Empty( FIELD->CITY ); AAdd( aRet, TRIM( FIELD->CITY ) + " " + TRIM( FIELD->ZIPCODE ) ); endif

   if Empty( aRet )
      return ""
   endif

return FW_ArrayAsList( aRet, CRLF )

//----------------------------------------------------------------------------//

static function ReadItemInfo( aRow, oBrw )

   local nSaveRec := ITEMS->( RECNO() )
   local lValid   := .f.

   if ITEMS->( DBSEEK( aRow[ 3 ] ) )
      aRow[ 4 ]      := TRIM( ITEMS->NAME )
      if aRow[ 5 ] == 0
         aRow[ 5 ]   := 1
      endif
      aRow[ 6 ]      := ITEMS->UNIT
      aRow[ 7 ]      := ITEMS->PRICE
      lValid         := .t.
   endif
   ITEMS->( DBGOTO( nSaveRec ) )

   if oBrw != nil
      oBrw:RefreshCurrent()
      oBrw:MakeTotals()
      oBrw:oWnd:Update()
   endif

return lValid

//----------------------------------------------------------------------------//

static function ViewInvoice( oBrw )

   local oPrn, oFontTitle, oFontBold, oFontText, oPen, n
   local nVal, nPage, nItemsByPage := 10
   local aItems := InvItems->( ;
                   FW_DbfToArray( nil, ;
                   { || InvItems->INVNUM == Invoices->INVNUM } ) )

   PRINT oPrn NAME "INVOICE" PREVIEW

   DEFINE FONT oFontTitle NAME "Arial" SIZE 0, -19 BOLD OF oPrn
   DEFINE FONT oFontBold  NAME "Arial" SIZE 0, -12 BOLD OF oPrn
   DEFINE FONT oFontText  NAME "Arial" SIZE 0, -12 OF oPrn
   DEFINE PEN oPen WIDTH 11

   for nPage = 1 to ( Len( aItems ) / nItemsByPage ) + 1
      PAGE
         oPrn:CmSay( 3.1, 2.3, "Company Name", oFontTitle )

     oPrn:CmBox( 4.4, 10.9, 7.7, 20.15, oPen )
     oPrn:CmSay( 4.7, 11.5, oBrw:Client:Value, oFontBold )
/*
      oPrn:CmSay( 5.4, 11.5, "Address 1", oFontText )
      oPrn:CmSay( 6.1, 11.5, "Address 2", oFontText )
      oPrn:CmSay( 6.8, 11.5, "City", oFontText )
*/
         @ 5.4, 11.5 PRINT TO oPrn TEXT oBrw:Address:Value SIZE 7.0 CM FONT oFontText

     oPrn:CmBox( 8.15, 2.20, 8.75, 20.15, oPen )
     oPrn:CmSay( 8.16,  2.30, "C.I.F.:", oFontBold )
     oPrn:CmSay( 8.16,  6.00, "Invoice n�:", oFontBold )
     oPrn:CmSay( 8.16,  8.30, oBrw:InvNum:Value, oFontText )
     oPrn:CmSay( 8.16, 11.20, "Date:", oFontBold )
     oPrn:CmSay( 8.20, 12.45, DToC( oBrw:Date:Value ), oFontText )
     oPrn:CmSay( 8.16, 15.60, "PayDate:", oFontBold )
     oPrn:CmSay( 8.20, 17.50, DToC( oBrw:PayDate:Value ), oFontText )

     oPrn:CmBox( 8.90, 2.20, 9.50, 20.15, oPen )
     oPrn:CmSay ( 8.91, 2.30, "Observations:", oFontBold )

     oPrn:CmBox( 9.65, 2.20, 23.25, 20.15, oPen )
     oPrn:CmLine( 9.65, 5.20, 23.25, 5.20, oPen )
     oPrn:CmLine( 9.65, 12.20, 23.25, 12.20, oPen )
     oPrn:CmLine( 9.65, 13.80, 23.25, 13.80, oPen )
     oPrn:CmLine( 9.65, 16.10, 23.25, 16.10, oPen )
     oPrn:CmLine( 9.65, 17.10, 23.25, 17.10, oPen )
     oPrn:CmLine( 10.20, 2.20, 10.20, 20.15, oPen )

     oPrn:CmSay( 9.66,  2.30, "Code", oFontBold )
     oPrn:CmSay( 9.66,  5.30, "Description", oFontBold )
     oPrn:CmSay( 9.66, 12.30, "Quantity", oFontBold )
     oPrn:CmSay( 9.66, 14.00, "Price", oFontBold )
     oPrn:CmSay( 9.66, 16.15, "Disc", oFontBold )
     oPrn:CmSay( 9.66, 18.20, "Amount", oFontBold )

  // "INVNUM,SERIAL,ITEMCODE,ITEMNAME,QUANTITY,UNIT,PRICE,DISCOUNT,RECNO()"
  //     1      2       3       4        5       6     7      8
     for n = ( ( nPage - 1 ) * nItemsByPage ) + 1 to Min( Len( aItems ), nItemsByPage * nPage )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 3, aItems[ n ][ 3 ], oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 5.5, aItems[ n ][ 4 ], oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 12.8, AllTrim( Str( aItems[ n ][ 5 ] ) ), oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 14.5, AllTrim( Str( aItems[ n ][ 7 ] ) ), oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 16.5, AllTrim( Str( aItems[ n ][ 8 ] ) ), oFontText )
        nVal  := ROUND( aItems[ n ][ 5 ] * aItems[ n ][ 7 ] - aItems[ n ][ 8 ], 0 )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 18.5, AllTrim( Str( nVal ) ), oFontText )
     next

     oPrn:CmBox( 23.40, 2.20, 27.20, 20.15, oPen )
     oPrn:CmLine( 24.00, 2.20, 24.00, 20.15, oPen )
     oPrn:CmLine( 23.40, 4.95, 26.20, 4.95, oPen )
     oPrn:CmLine( 23.40, 6.45, 26.20, 6.45, oPen )
     oPrn:CmLine( 23.40, 9.35, 26.20, 9.35, oPen )
     oPrn:CmLine( 23.40, 10.95, 26.20, 10.95, oPen )
     oPrn:CmLine( 23.40, 13.80, 26.20, 13.80, oPen )
     oPrn:CmLine( 23.40, 16.65, 26.20, 16.65, oPen )
     oPrn:CmSay( 23.50,  2.40, "BASE", oFontBold )
     oPrn:CmSay( 23.50,   5.20, "%VAT", oFontBold )
     oPrn:CmSay( 23.50,   6.75, "CUOTE", oFontBold )
     oPrn:CmSay( 23.50,   9.60, "%RE", oFontBold )
     oPrn:CmSay( 23.50,  11.20, "CUOTE", oFontBold )
     oPrn:CmSay( 23.50,  14.10, "AMOUNT", oFontBold )
     oPrn:CmSay( 23.50, 16.95, "SUM BASES:", oFontBold )

     oPrn:CmSay( 23.50 + 1.5,  2.40, cValToStr( oBrw:Amount:Value ), oFontText )
     oPrn:CmSay( 23.50 + 1.5,  5.20, cValToStr( oBrw:TaxRate:Value ), oFontText )

     oPrn:CmSay( 26.44,  2.40, "TOTAL VAT:", oFontBold )
     oPrn:CmSay( 26.44,  5.50, cValToStr( oBrw:Tax:Value ), oFontText )
     oPrn:CmSay( 26.44,  7.70, "TOTAL R.E.:", oFontBold )
     oPrn:CmSay( 26.44, 13.35, "TOTAL INVOICE", oFontBold )
     oPrn:CmSay( 26.44, 17.50, cValToStr( oBrw:Total:Value ), oFontBold )
  ENDPAGE
   next

   ENDPRINT

   oFontTitle:End()
   oFontBold:End()
   oFontText:End()
   oPen:End()

return nil

//----------------------------------------------------------------------------//

static function OpenDataBases()  

   oCn = maria_Connect( "localhost", "fwh", "fivetec1_antonio", "1234" )  
     
if oCn == nil
MsgStop( "Error connecting to the DataBase" )
return nil
endif
return oCn //----------------------------------------------------------------------------// static function BrwBtnBar( oBrw, oWnd ) local oBar DEFINE BUTTONBAR oBar OF oWnd 2007 SIZE 70, 60 //70 DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "add" ; ACTION oBrw:EditSource( .T. ) DEFINE BUTTON OF oBar PROMPT "Edit" RESOURCE "edit" ; ACTION oBrw:EditSource() DEFINE BUTTON OF oBar PROMPT "Delete" RESOURCE "del" /* DEFINE BUTTON OF oBar PROMPT "Preview" RESOURCE "report" ; ACTION ViewInvoice( oBrw ) DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ; ACTION oWndInvoices:End() */ return oBar //----------------------------------------------------------------------------// static function BrwColors( oBrw ) local cClrBack oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW oBrw:bClrStd = { || If( oBrw:KeyNo() % 2 == 0, ; { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_BLACK ),; RGB( 198, 255, 198 ) }, ; { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_BLACK ),; RGB( 232, 255, 232 ) } ) } oBrw:bClrSel = { || { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_WHITE ),; RGB( 0x33, 0x66, 0xCC ) } } cClrBack = Eval( oBrw:bClrSelFocus )[ 2 ] oBrw:bClrSelFocus = { || { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_WHITE ),; cClrBack } } oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) ) oBrw:lHScroll := .f. return nil //----------------------------------------------------------------------------// static function BrwRecSel( oBrw, cHead ) WITH OBJECT oBrw :lFooter := .t. if "REC" $ Upper( cHead ) :bRecSelHeader := { || "RecNo" } :bRecSelData := { |o| o:BookMark } :bRecSelClick := { |o| ( o:cAlias )->( OrdSetFocus( 0 ) ), ; AEval( o:aCols, { |c| c:cOrder := "" } ), ; o:Refresh() } else :bRecSelHeader := { || "SlNo" } :bRecSelData := { |o| o:KeyNo } endif :bRecSelFooter := { |o| o:nLen } :nRecSelWidth := Replicate( '9', Len( cValToChar( Eval( oBrw:bKeyCount, oBrw ) ) ) + 1 ) END retur nil //----------------------------------------------------------------------------// static function EditItems( oRec ) local oDlg local lSave := .F. local oFont local oBtn local lAdd := ( oRec:RecNo == 0 ) DEFINE FONT oFont NAME "Tahoma" SIZE 0, -15 DEFINE DIALOG oDlg SIZE 402, 158 PIXEL FONT oFont ; TITLE If( lAdd, "New Item", "Edit Item" ) @ 12, 10 SAY "Code:" OF oDlg SIZE 19, 8 PIXEL FONT oFont @ 10, 36 GET oRec:Code OF oDlg SIZE 55, 12 PIXEL FONT oFont PICTURE "@!" UPDATE ; VALID ! Empty( oRec:Code ) @ 26, 10 SAY "Name:" OF oDlg SIZE 21, 8 PIXEL FONT oFont @ 24, 36 GET oRec:Name OF oDlg SIZE 155, 12 PIXEL FONT oFont ; VALID !Empty( oRec:Name ) UPDATE @ 40, 10 SAY "Unit:" OF oDlg SIZE 18, 8 PIXEL FONT oFont // @ 38, 36 GET oRec:Unit OF oDlg SIZE 44, 12 PIXEL FONT oFont RIGHT ; @ 38,38 COMBOBOX oRec:Unit SIZE 44,12 PIXEL OF oDlg ; ITEMS { "Items","K.G","Metre","Litre" } @ 40, 10 + 111 SAY "Price:" OF oDlg SIZE 18, 8 PIXEL FONT oFont @ 38, 36 + 111 GET oRec:Price OF oDlg SIZE 44, 12 PIXEL PICTURE "9999999.99" FONT oFont RIGHT ; VALID oRec:Price > 0 UPDATE @ 60, 111 BTNBMP oBtn PROMPT "Save" OF oDlg SIZE 42, 14 PIXEL FLAT ; WHEN oRec:Modified() ACTION (oDlg:End(), lSave := .T.) @ 60, 155 BTNBMP oBtn PROMPT "Cancel" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End()) oBtn:lCancel := .t. // oRec:bValid := { || !Duplicate( oRec:Code, "CODE", oRec:RecNo ) } ACTIVATE DIALOG oDlg CENTERED ; ON PAINT ( oDlg:Box( 10, 10, 110, 392 ) ) if lSave oRec:Save( .T. ) // Param .t. to check oRec:bValid endif return nil //----------------------------------------------------------------------------// static function EditClients( oRec ) local oDlg local lSave := .F. local oFont local oBtn local lAdd := ( oRec:RecNo == 0 ) DEFINE FONT oFont NAME "TAHOMA" SIZE 0, 15 DEFINE DIALOG oDlg SIZE 422, 326 PIXEL ; //FROM 100, 100 TO 426,522; TITLE If( lAdd, "New Client", "Edit Client" ) FONT oFont @ 12, 10 SAY "Code:" OF oDlg SIZE 19, 8 PIXEL @ 10, 46 GET oRec:Code OF oDlg SIZE 55, 12 PIXEL PICTURE "@!" UPDATE ; VALID ! Empty( oRec:Code ) @ 26, 10 SAY "First:" OF oDlg SIZE 15, 8 PIXEL @ 24, 46 GET oRec:First OF oDlg SIZE 105, 12 PIXEL UPDATE ; VALID ! Empty( oRec:First ) @ 40, 10 SAY "Last:" OF oDlg SIZE 15, 8 PIXEL @ 38, 46 GET oRec:Last OF oDlg SIZE 105, 12 PIXEL UPDATE @ 54, 10 SAY "Address1:" OF oDlg SIZE 31, 8 PIXEL @ 52, 46 GET oRec:Address1 OF oDlg SIZE 155, 12 PIXEL UPDATE @ 68, 10 SAY "Address2:" OF oDlg SIZE 31, 8 PIXEL FONT oFont @ 66, 46 GET oRec:Address2 OF oDlg SIZE 155, 12 PIXEL UPDATE @ 82, 10 SAY "City:" OF oDlg SIZE 13, 8 PIXEL @ 80, 46 GET oRec:City OF oDlg SIZE 105, 12 PIXEL UPDATE @ 96, 10 SAY "Zipcode:" OF oDlg SIZE 28, 8 PIXEL @ 94, 46 GET oRec:Zipcode OF oDlg SIZE 105, 12 PIXEL UPDATE @ 110, 10 SAY "Phone:" OF oDlg SIZE 23, 8 PIXEL @ 108, 46 GET oRec:Phone OF oDlg SIZE 105, 12 PIXEL UPDATE @ 124, 10 SAY "Email:" OF oDlg SIZE 19, 8 PIXEL @ 122, 46 GET oRec:Email OF oDlg SIZE 105, 12 PIXEL UPDATE @ 144, 121 BTNBMP oBtn PROMPT "Save" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End(), lSave := .T.) ; WHEN oRec:Modified() @ 144, 165 BTNBMP oBtn PROMPT "Cancel" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End()) oBtn:lCancel := .t. // oRec:bValid := { || !Duplicate( oRec:Code, "CODE", oRec:RecNo ) } ACTIVATE DIALOG oDlg CENTERED ; ON PAINT ( oDlg:Box( 10, 10, 278, 412 ) ) IF lSave oRec:Save( .T. ) ENDIF RETURN NIL //----------------------------------------------------------------------------// static function Duplicate( uVal, cOrder, nThisRec ) local nSaveRec := RECNO() local cSaveOrd := OrdSetFocus() local lExists := .f. DEFAULT nThisRec := nSaveRec OrdSetFocus( cOrder ) lExists := DBSEEK( uVal ) .and. RECNO() != nThisRec if ! Empty( cSaveOrd ) OrdSetFocus( cSaveOrd ) endif DBGOTO( nSaveRec ) return lExists //----------------------------------------------------------------------------// static function TableLookUp( nRow, nCol, oCol, nKey, uSource, uRetCol, aCols ) local oDlg, oBrw, uRet local aPoint local oFont, oBold local aCellCoor := oCol:oBrw:aCellCoor() DEFAULT uRetCol := 1 DEFINE FONT oFont NAME "ARIAL" SIZE 0,-12 DEFINE FONT oBold NAME "ARIAL" SIZE 0,-12 BOLD aPoint := ClientToScreen( oCol:oBrw:hWnd, { aCellCoor[ 1 ], aCellCoor[ 2 ] } ) ( uSource )->( DBSEEK( oCol:Value, .t. ), If( Eof(), DBGOBOTTOM(), nil ) ) DEFINE DIALOG oDlg SIZE 300,300 PIXEL TRUEPIXEL ; STYLE WS_POPUP OF oCol:oBrw FONT oFont ; COLOR CLR_BLACK, 1 oDlg:nSeeThroClr := 1 @ aCellCoor[ 3 ] - aCellCoor[ 1 ],0 XBROWSE oBrw SIZE 0,0 PIXEL OF oDlg ; DATASOURCE uSource AUTOCOLS ; AUTOSORT CELL LINES NOBORDER ; COLOR CLR_BLACK, RGB( 232, 255, 232 ) WITH OBJECT oBrw :lHScroll := .f. :lRecordSelector := .f. :lDrawBorder := .t. // :lIncrFilter := .t. :lSeekWild := .t. :oCol( uRetCol ):oDataFont := oBold if ValType( uSource ) == 'C' :cFilterFld := "DBRECORDINFO( 7 )" endif :bKeyDown := { |nKey| If( nKey == VK_RETURN, ( uRet := oBrw:oCol( uRetCol ):Value, oDlg:End() ), nil ) } :bKeyChar := { |nKey| If( nKey == VK_ESCAPE, ( oBrw:Seek( "" ), oDlg:End() ), nil ) } :bLDClickDatas := { || uRet := oBrw:oCol( uRetCol ):Value, oDlg:End() } :AutoFit() :CreateFromCode() END @ 00,00 SAY oBrw:oSeek PROMPT oBrw:cSeek PICTURE "@!" ; SIZE aCellCoor[ 4 ] - aCellCoor[ 2 ], aCellCoor[ 3 ] - aCellCoor[ 1 ] PIXEL OF oDlg COLOR CLR_HRED, CLR_YELLOW ; FONT oCol:DataFont WITH OBJECT oBrw:oSeek :lWantClick := .t. :bLClicked := { || oDlg:End() } END ACTIVATE DIALOG oDlg ; ON PAINT ( oDlg:Box( 0,0,20,100 ) ) ; ON INIT BrwHelpDlgInit( oBrw, aPoint ) ; VALID ( oBrw:Seek( "" ), .t. ) RELEASE FONT oFont, oBold return uRet //----------------------------------------------------------------------------// static function BrwHelpDlgInit( oBrw, aPoint ) local oDlg := oBrw:oWnd local dy := oDlg:GetRect():nWidth - oDlg:GetCliRect():nWidth local aSize aSize := oBrw:BrwFitSize() oDlg:nWidth := aSize[ 1 ] + dy oDlg:nHeight := oBrw:nTop + aSize[ 2 ] oDlg:SetPos( aPoint[ 1 ], aPoint[ 2 ] ) oDlg:Shadow() return nil //----------------------------------------------------------------------------// static function ViewInvoiceER( oBrw ) local oVRD local lPreview := .t. local cDruckerName := "" local nVal local aItems := InvItems->( ; FW_DbfToArray( nil, ; { || InvItems->INVNUM == Invoices->INVNUM } ) ) *---------------------------------------------------------- local aID_Strings := {} local aID := {} local aStrings := {} local cLogo := "" local cBezeichnung := "" local nPrintArea := 3 local n *---------------------------------------------------------- TPreview():lListViewHide := .T. EASYREPORT oVRD NAME "yinvoice\invoice.vrd" PREVIEW lPreview TO cDruckerName PRINTDIALOG IIF( lPreview, .F., .F. ) MODAL //----------------------------------------------------------------------------// //header //----------------------------------------------------------------------------// #DEFINE ER_COMPANY 201 #DEFINE ER_ADDRESS 500 #DEFINE ER_CIF 501 #DEFINE ER_INVOICE 602 #DEFINE ER_DATE 502 #DEFINE ER_PAYDATE 603 PRINTAREA 5 OF oVRD PRINTAREA 1 OF oVRD ; ITEMIDS { ER_COMPANY ,ER_ADDRESS, ER_CIF, ER_INVOICE, ER_DATE, ER_PAYDATE } ; ITEMVALUES { OBRW:CLIENT:VALUE, OBRW:ADDRESS:VALUE, "100", "220178992", DToC( oBrw:Date:Value ), DToC( oBrw:PayDate:Value ) } //----------------------------------------------------------------------------// // Data Header //----------------------------------------------------------------------------// PRINTAREA 2 OF oVRD //----------------------------------------------------------------------------// // Data //----------------------------------------------------------------------------// #DEFINE ER_CODE 200 #DEFINE ER_DESCRIPTION 201 #DEFINE ER_QUANTITY 202 #DEFINE ER_PRICE 203 #DEFINE ER_DISC 204 #DEFINE ER_AMOUNT 205 for n = 1 to Len( aItems ) PRINTAREA nPrintArea OF oVRD ; ITEMIDS { ER_CODE ,; ER_DESCRIPTION ,; ER_QUANTITY ,; ER_PRICE ,; ER_DISC ,; ER_AMOUNT } ; ITEMVALUES { aItems[ n, 3 ],; aItems[ n, 4 ],; AllTrim( Str( aItems[ n, 5 ] ) ),; AllTrim( Str( aItems[ n, 7 ] ) ),; AllTrim( Str( aItems[ n, 8 ] ) ),; AllTrim( Str( ROUND( aItems[ n, 5 ] * aItems[ n, 7 ] - aItems[ n, 8 ], 0 ) ) ) } if nPrintArea = 3 nPrintArea := 6 else nPrintArea := 3 endif next #UNDEF ER_AMOUNT //----------------------------------------------------------------------------// //Footer //----------------------------------------------------------------------------// #DEFINE ER_BASE 310 #DEFINE ER_VAT 311 #DEFINE ER_TOTALVAT 312 #DEFINE ER_TOTALINVOICE 313 PRINTAREA 4 OF oVRD ; ITEMIDS { ER_BASE ,; ER_VAT ,; ER_TOTALVAT ,; ER_TOTALINVOICE } ; ITEMVALUES { cValToStr( oBrw:Amount:Value ) ,; cValToStr( oBrw:TaxRate:Value ) ,; cValToStr( oBrw:Tax:Value ) ,; cValToStr( oBrw:Total:Value ) } oVRD:End() return nil //----------------------------------------------------------------------------//

Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 1:36 pm
by Antonio Linares

Enhanced version:

yunusm.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "easyrep.ch"

REQUEST DBFCDX

static oWndMain, oWndInvoices, oWndClients, oWndItems
static aBlankItem
static cItemFlds  := "INVNUM,SERIAL,ITEMCODE,ITEMNAME,QUANTITY,UNIT,PRICE,DISCOUNT,ID"
static nTaxRate   := 0.0
static oCn, oRsClients

//----------------------------------------------------------------------------//

function Main()

   local oBrush, oFont

   OpenDataBases()

   DEFINE BRUSH oBrush RESOURCE "background"
   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-12

//   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE WINDOW oWndMain TITLE "Invoicing" MDI MENU BuildMenu() VSCROLL HSCROLL BRUSH oBrush
   oWndMain:SetFont( oFont )

   BuildMainBar()

   DEFINE MSGBAR PROMPT "Invoicing app" ;
      OF oWndMain 2007 KEYBOARD DATE

   ACTIVATE WINDOW oWndMain MAXIMIZED

   RELEASE BRUSH oBrush

return nil

//----------------------------------------------------------------------------//

INIT PROCEDURE inv_init

   SET DATE BRITISH
   SET CENTURY ON
   SET EPOCH TO ( YEAR( DATE() ) - 50 )

   RDDSETDEFAULT( "DBFCDX" )
   SET DELETED ON

   SetGetColorFocus()

   aBlankItem := { "", 0, "", "", 0.0, "", 0.0, 0.0, 0 }

return

//----------------------------------------------------------------------------//

static function BuildMainBar()

   local oBar

   DEFINE BUTTONBAR oBar OF oWndMain 2007 SIZE 70, 60 //70

   DEFINE BUTTON OF oBar PROMPT "Invoices" RESOURCE "code" ;
      ACTION Invoices()

   DEFINE BUTTON OF oBar PROMPT "Clients" RESOURCE "clients" ;
      ACTION Clients()

   DEFINE BUTTON OF oBar PROMPT "Items" RESOURCE "relation" ;
      ACTION Items()

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End()

return nil

//----------------------------------------------------------------------------//

static function BuildMenu()

   local oMenu

   MENU oMenu

  MENUITEM "Tasks"
  MENU
     MENUITEM "Invoices" ACTION Invoices()
     //MENUITEM "Invoices items" ACTION ( "invitems" )->( XBrowse() )
     MENUITEM "Clients"  ACTION Clients()
     MENUITEM "Items"    ACTION Items()
     SEPARATOR
     MENUITEM "Exit" ACTION oWndMain:End()
  ENDMENU

  oMenu:AddMDI()
  oMenu:AddHelp( "Invoicing app", "(c) FiveTech Software" )

   ENDMENU

return oMenu

//----------------------------------------------------------------------------//

static function Clients()

   local oBrw, cClrBack, cAlias
   local oBar, oMsgBar, oMsgDeleted

   if oWndClients == nil
      oRsClients = oCn:RowSet( "SELECT * FROM clients2 ORDER BY code" )

  DEFINE WINDOW oWndClients MDICHILD OF oWndMain TITLE "Clients"

  @ 2, 0 XBROWSE oBrw OF oWndClients LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRsClients NOBORDER

  oBar  := BrwBtnBar( @oBrw, oWndClients )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION oBrw:Report( "Clients report",, .F.)

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndClients:End()

  cAlias = Alias()

  BrwColors( oBrw )
  // BrwRecSel( oBrw, "RECNO" )

  oBrw:bEdit  := { |oRec| EditClients( oRec ) }

  oBrw:CreateFromCode()
  oBrw:SetFocus()
  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }

  oWndClients:oClient = oBrw
  oWndClients:oControl = oBrw

  DEFINE MSGBAR oMsgBar OF oWndClients 2007

  ACTIVATE WINDOW oWndClients MAXIMIZED ;
     VALID ( oWndClients := nil, .T. )
   else
      oWndClients:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function Items()

   local oBrw, cClrBack
   local oBar, oMsgBar, oMsgDeleted, oRs

   if oWndItems == nil
      oRs = oCn:RowSet( "SELECT * FROM items ORDER BY code" )

  DEFINE WINDOW oWndItems MDICHILD OF oWndMain TITLE "Items"

  @ 2, 0 XBROWSE oBrw OF oWndItems LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs NOBORDER

  oBar  := BrwBtnBar( @oBrw, oWndItems )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION oBrw:Report( "Items report",, .F.)

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndItems:End()
  BrwColors( oBrw )
  // BrwRecSel( oBrw, "RECNO" )

  oBrw:bEdit  := { |oRec| EditItems( oRec ) }

  oBrw:CreateFromCode()
  oBrw:SetFocus()
  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }

  oWndItems:oClient = oBrw
  oWndItems:oControl = oBrw

  DEFINE MSGBAR oMsgBar OF oWndItems 2007

  ACTIVATE WINDOW oWndItems MAXIMIZED ;
     VALID ( oWndItems := nil, .T. )
   else
      oWndItems:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function Invoices()

   local oBrw, oChild, cClrBack, cCol
   local oBar, oMsgBar, oMsgDeleted, oRs1, oRs2

   if oWndClients == nil
      Clients()
   endif

   if oWndItems == nil
      Items()
   endif

   if oWndInvoices == nil
      oRs1 = oCn:RowSet( "SELECT * FROM invoices ORDER BY code" )
      oRs2 = oCn:RowSet( "SELECT * FROM invitems ORDER BY itemcode" )

  DEFINE WINDOW oWndInvoices MDICHILD OF oWndMain TITLE "Invoices"

  @ 60, 0 XBROWSE oBrw SIZE 0,200 PIXEL OF oWndInvoices LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs1 NOBORDER FOOTERS

  oBar  := BrwBtnBar( @oBrw, oWndInvoices )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION ViewInvoice( oBrw )

  DEFINE BUTTON OF oBar PROMPT "EasyReport" RESOURCE "report" ;
     ACTION ViewInvoiceER( oBrw )

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndInvoices:End()

  DEFINE MSGBAR oMsgBar OF oWndInvoices 2007

  BrwColors( oBrw )
  BrwRecSel( oBrw, "RECNO" )

  for each cCol in { "Amount", "Tax", "Total" }
     oBrw:oCol( cCol ):nFooterType  := AGGR_SUM
  next

  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }
  oBrw:bEdit = { | oRec | EditInvoice( oRec ) }
  oBrw:MakeTotals()
  oBrw:CreateFromCode()
  oBrw:SetFocus()

  oWndInvoices:oControl = oBrw

  @ oBar:nHeight + 200,0 XBROWSE oChild SIZE 0,-oMsgBar:nHeight PIXEL OF oWndInvoices ;
     DATASOURCE oRs2 ;
     COLUMNS "ItemCode", "ItemName", "Quantity", "Unit", "Price", ;
             "ROUND(QUANTITY*PRICE,0)", "DISCOUNT","ROUND(QUANTITY*PRICE,0)-DISCOUNT" ;
     HEADERS "ItmCode", nil, nil, nil, nil, "Amount", "Discount", "Net Amount" ;
     LINES NOBORDER FOOTERS

  BrwColors( oChild )
  // BrwRecSel( oChild, "KEY" )

  for each cCol in { "Amount", "Discount", "Net Amount" }
     WITH OBJECT oChild:oCol( cCol )
        :nFooterType   := AGGR_SUM
     END
  next
  oChild:MakeTotals()
  oChild:CreateFromCode()

  oBrw:bChange   := { || oChild:Refresh(), oChild:MakeTotals(), oChild:GoTop() }

  oWndInvoices:bResized := < ||
     local oRect    := oWndInvoices:GetCliRect()
     oBrw:nHeight   := ( oRect:nHeight - oBar:nHeight - oMsgBar:nHeight ) * 0.6
     oChild:nTop    := oBrw:nTop + oBrw:nHeight
     return nil
     >

  oWndInvoices:bPostEnd   := { || oWndInvoices := nil }

  ACTIVATE WINDOW oWndInvoices MAXIMIZED

   else
      oWndInvoices:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function EditInvoice( oRec )

   local lNew     := ( oRec:RecNo == 0 )
   local oDlg, oBrush, oFont, oBold, oLarge
   local oBrw, cCol, bInit, oBtn
   local aItems
   local oGetClient, cClient, bCliInit
   local nHt      := Int( ScreenHeight() * 0.8 )
   local nWd      := 1100
   local lSave    := .f.

   if lNew
      oRec:InvNum    := ""
      oRec:Date      := Date()
      oRec:TaxRate   := nTaxRate
      oRec:InvNum    := "     "
      aItems         := { AClone( aBlankItem ) }
   else
      aItems = FW_RowSetToArray( oCn:RowSet( "SELECT " + cItemFlds + ;
         " FROM invitems WHERE INVNUM = '" + oRec:InvNum + "' ORDER BY SERIAL" ),;
         cItemFlds )
   endif

   DEFINE BRUSH oBrush RESOURCE "PAPER"
   DEFINE FONT oLarge NAME "VERDANA" SIZE 0,-30 BOLD
   DEFINE FONT oFont NAME  "TAHOMA"  SIZE 0,-15
   DEFINE FONT oBold NAME  "TAHOMA"  SIZE 0,-15 BOLD

   DEFINE DIALOG oDlg SIZE nWd, nHt PIXEL FONT oFont TRUEPIXEL ;
      TITLE If( lNew, "NEW ", "EDIT " ) + "INVOICE" TRANSPARENT ;
      BRUSH oBrush

//   @  20, 40 SAY "INVOICE" SIZE 260,36 PIXEL OF oDlg FONT oLarge ;
   @  20, nWd/2-100 SAY "INVOICE" SIZE 200,36 PIXEL OF oDlg FONT oLarge CENTER

   @ 020, nWd - 190 GET oRec:InvNum PICTURE "@!" SIZE 150,26 PIXEL OF oDlg ;
      VALID ! Empty( oRec:InvNum )

   @ 050, nWd - 190 GET oRec:Date   SIZE 150,26 PIXEL OF oDlg RIGHT ;
                  ACTION oRec:Date := Min( MsgDate( oRec:Date ), Date() )

   @  80-60, 40 SAY "Client:" SIZE 100,24 PIXEL OF oDlg

   @  80-60,150 GET oGetClient VAR oRec:Code SIZE 150,26 PIXEL OF oDlg ;
         ACTION ( PopupBrowse( oRsClients, oGetClient ), ;
                  ReadClientInfo( oRec, oDlg ) ) ;
         VALID ( ReadClientInfo( oRec, oDlg ) )

   @ 125-60, 60 SAY oRec:Client SIZE 200,24 PIXEL OF oDlg FONT oBold UPDATE
   @ 150-60, 60 SAY oRec:Address SIZE 200, 60 PIXEL OF oDlg UPDATE

   @ 180-60,310 SAY "Text :" SIZE 100,24 PIXEL OF oDlg
   @ 204-60,310 GET oRec:Details SIZE nWd-310-40,26 PIXEL OF oDlg UPDATE

   @ 240-60,040 XBROWSE oBrw SIZE -40,-150+45 PIXEL OF oDlg ;
      DATASOURCE aItems ;
      COLUMNS 3,4,5,6,7,8 ;
      HEADERS "ITEM", "DETAILS", "QTY", "UNIT","PRICE","DISCOUNT" ;
      PICTURES "@!", nil, "9999.999", nil, "999.99", "999,999,999" ;
      COLSIZES nil, 30 ;
      CELL LINES NOBORDER FASTEDIT FOOTERS

   ADD TO oBrw AT 6 HEADER "AMOUNT" DATA ROUND( oBrw:aRow[5] * oBrw:aRow[7], 0 ) ;
      PICTURE "999,999,999"

   ADD TO oBrw HEADER "NET" DATA ROUND( oBrw:aRow[5] * oBrw:aRow[7] - oBrw:aRow[ 8 ], 0 ) ;
      PICTURE "999,999,999"

   for each cCol in { "amount", "discount", "net" }
      WITH OBJECT oBrw:oCol( cCol )
         :nFooterType   := AGGR_SUM
      END
   next

   for each cCol in { "qty", "price", "discount" }
      WITH OBJECT oBrw:oCol( cCol )
         :nEditType     := EDIT_GET
         :bEditValid    := { |o| o:VarGet() >= 0 }
         :bOnChange     := { || oBrw:MakeTotals( { "amount", "net" } ), oBrw:RefreshFooters(), oDlg:Update() }
      END
   next

   for each cCol in { "details", "unit", "amount", "net" }
      oBrw:oCol( cCol ):bClrStd  := { || { CLR_BLACK, RGB( 240, 240, 240 ) } }
   next

   // AutoAppendCode
   WITH OBJECT oBrw
      :AddVar( "AAPPEND", nil )
      :bClrStd    := { || If( oBrw:aRow == oBrw:aAppend, { CLR_BLACK, CLR_YELLOW }, { CLR_BLACK, oBrw:nClrPane } ) }

  :bChange    := { || If( oBrw:nArrayAt < oBrw:nLen, CheckAppendRow( oBrw ), nil ) }

  :bPastEof   := { || If( oBrw:aAppend != nil .and. Empty( oBrw:aAppend[ 3 ] ), nil, ;
           ( AAdd( oBrw:aArrayData, oBrw:aAppend := AClone( aBlankItem ) ), ;
             oBrw:GoBottom(), oBrw:GoLeftMost(), oBrw:RefreshCurrent(), ;
             oBrw:MakeTotals(), oBrw:Refresh() ) ) }

  :bKeyDown   := { |k| If( k == VK_DELETE, ( oBrw:aAppend := nil, oBrw:Delete(), 0 ), nil ) }

   END

   WITH OBJECT oBrw:aCols[ 1 ]
      :nEditType     = EDIT_BUTTON
      :bEditBlock    = { | nRow, nCol, oCol, nKey | TableLookUp( nRow, nCol, oCol, nKey, "ITEMS" ) }
      :bOnChange     = { || oBrw:aAppend := nil, ReadItemInfo( oBrw:aRow, oBrw ), oBrw:RefreshCurrent(), ;
                            oBrw:MakeTotals(), oBrw:RefreshFooters(), oDlg:Update() }
   END

   WITH OBJECT oBrw
      :lFlatStyle    := .t.
      :nStretchCol   := 2
      :lHScroll      := .f.
      :bOnRefresh    := { || oDlg:Update() }
      //
      BrwRecSel( oBrw, "KEYNO" )
      //
      :MakeTotals()
      :CreateFromCode()
   END

   @ nHt - 139 + 45, nWd - 380 SAY "TAX @" ;
      SIZE 80,24 PIXEL OF oDlg RIGHT

   @ nHt - 140 + 45, nWd - 280 GET oRec:TaxRate PICTURE "99.99 %" ;
      SIZE 100,26 PIXEL OF oDlg RIGHT ;
      VALID ( If( oRec:TaxRate >= 0, ( oDlg:Update(), .t. ), .f. ) )

   @ nHT - 139 + 45, nWd - 170 SAY ;
      ( oRec:Tax := ROUND( oBrw:Net:nTotal * oRec:TaxRate / 100, 0 ) ) ;
      PICTURE "999,999,999" SIZE 105,24 PIXEL OF oDlg UPDATE RIGHT

   @ nHt - 105 + 45, nWd - 270 SAY "TOTAL" SIZE 80, 24 PIXEL OF oDlg RIGHT

   @ nHt - 105 + 45, nWd - 170 SAY ;
      ( oRec:Total := oBrw:Net:nTotal + oRec:Tax ) ;
      PICTURE "999,999,999" SIZE 105, 24 PIXEL OF oDlg UPDATE RIGHT

/*
   @ nHt - 60, nWd - 260 BTNBMP PROMPT "Save"  SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION ( lSave := .t., oDlg:End() )

   @ nHt - 60, nWd - 140 BTNBMP oBtn PROMPT "Cancel" SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION oDlg:End()
   oBtn:lCancel   := .t.
*/
   @ nHt - 60, 040 BTNBMP PROMPT "Save"  SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION ( lSave := .t., oDlg:End() )

   @ nHt - 60, 160 BTNBMP oBtn PROMPT "Cancel" SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION oDlg:End()
   oBtn:lCancel   := .t.



   ACTIVATE DIALOG oDlg CENTERED ;
      ON PAINT (  oDlg:Box( 110-60, 40, 230-60, 300 ), ;
                  oDlg:Line( nHt - 112 + 45, nWd - 170, nHt - 112 + 45, nWd - 55 ), ;
                  oDlg:Line( nHt -  78 + 45, nWd - 170, nHt -  78 + 45, nWd - 55 ), ;
                  oDlg:Line( nHt -  75 + 45, nWd - 170, nHt -  75 + 45, nWd - 55 )  )

   if lSave
      CheckAppendRow( oBrw )
      if Empty( aItems ) .or. Empty( oRec:InvNum ) .or. Empty( oRec:Code ) .or. oRec:Total <= 0
      else

     oRec:Amount    := oBrw:Net:nTotal

     if ! Empty( oBrw:aDeleted )
        AEval( oBrw:aDeleted, { |a| a[ 9 ] := -a[ 9 ] } )
        IIT->( FW_SaveArrayToDBF( cItemFlds, oBrw:aDeleted ) )
     endif
     AEval( aItems, { |a| a[ 1 ] := oRec:InvNum } )
     AEval( aItems, { |a,i| a[ 2 ] := i } )
     IIT->( FW_SaveArrayToDBF( cItemFlds, aItems ) )
     oRec:Save()
     WITH OBJECT oRec:oBrw
        :MakeTotals()
        :RefreshFooters()
        Eval( :bChange, oRec:oBrw )
     END
  endif

   endif

   RELEASE FONT oFont, oLarge
   RELEASE BRUSH oBrush

return nil

//----------------------------------------------------------------------------//

static function CheckAppendRow( oBrw, aAppend )

   if Empty( ATail( oBrw:aArrayData )[ 3 ] )
      ASize( oBrw:aArrayData, oBrw:nLen - 1 )
      oBrw:aAppend  := nil
      oBrw:Refresh()
   endif

return nil

//----------------------------------------------------------------------------//

static function ReadClientInfo( oRec, oDlg )

   local oRs := oCn:RowSet( "SELECT first, last, address1, address2, city, zipcode FROM clients2 WHERE code = '" + oRec:Code + "'" )
   local lValid   := .f.
   local aRet := {}

   if oRs:RecCount > 0
      oRs:GoTop()
      oRec:Client    := TRIM( oRs:FIRST ) + " " + TRIM( oRs:LAST )
      if ! Empty( oRs:ADDRESS1 ); AAdd( aRet, TRIM( oRs:ADDRESS1 ) ); endif
      if ! Empty( oRs:ADDRESS2 ); AAdd( aRet, TRIM( oRs:ADDRESS2 ) ); endif
      if ! Empty( oRs:CITY ); AAdd( aRet, TRIM( oRs:CITY ) + " " + TRIM( oRs:ZIPCODE ) ); endif
      oRec:Address   := If( Empty( aRet ), "", FW_ArrayAsList( aRet, CRLF ) )
      lValid         := .t.
   endif

   if oDlg != nil
      oDlg:Update()
   endif

return lValid

//----------------------------------------------------------------------------//

static function PickAddress()

   local aRet  := {}

   if ! Empty( FIELD->ADDRESS1 ); AAdd( aRet, TRIM( FIELD->ADDRESS1 ) ); endif
   if ! Empty( FIELD->ADDRESS2 ); AAdd( aRet, TRIM( FIELD->ADDRESS2 ) ); endif
   if ! Empty( FIELD->CITY ); AAdd( aRet, TRIM( FIELD->CITY ) + " " + TRIM( FIELD->ZIPCODE ) ); endif

   if Empty( aRet )
      return ""
   endif

return FW_ArrayAsList( aRet, CRLF )

static function ReadItemInfo( aRow, oBrw )

   local nSaveRec := ITEMS->( RECNO() )
   local lValid   := .f.

   if ITEMS->( DBSEEK( aRow[ 3 ] ) )
      aRow[ 4 ]      := TRIM( ITEMS->NAME )
      if aRow[ 5 ] == 0
         aRow[ 5 ]   := 1
      endif
      aRow[ 6 ]      := ITEMS->UNIT
      aRow[ 7 ]      := ITEMS->PRICE
      lValid         := .t.
   endif
   ITEMS->( DBGOTO( nSaveRec ) )

   if oBrw != nil
      oBrw:RefreshCurrent()
      oBrw:MakeTotals()
      oBrw:oWnd:Update()
   endif

return lValid

//----------------------------------------------------------------------------//

static function ViewInvoice( oBrw )

   local oPrn, oFontTitle, oFontBold, oFontText, oPen, n
   local nVal, nPage, nItemsByPage := 10
   local aItems := InvItems->( ;
                   FW_DbfToArray( nil, ;
                   { || InvItems->INVNUM == Invoices->INVNUM } ) )

   PRINT oPrn NAME "INVOICE" PREVIEW

   DEFINE FONT oFontTitle NAME "Arial" SIZE 0, -19 BOLD OF oPrn
   DEFINE FONT oFontBold  NAME "Arial" SIZE 0, -12 BOLD OF oPrn
   DEFINE FONT oFontText  NAME "Arial" SIZE 0, -12 OF oPrn
   DEFINE PEN oPen WIDTH 11

   for nPage = 1 to ( Len( aItems ) / nItemsByPage ) + 1
      PAGE
         oPrn:CmSay( 3.1, 2.3, "Company Name", oFontTitle )

     oPrn:CmBox( 4.4, 10.9, 7.7, 20.15, oPen )
     oPrn:CmSay( 4.7, 11.5, oBrw:Client:Value, oFontBold )
/*
      oPrn:CmSay( 5.4, 11.5, "Address 1", oFontText )
      oPrn:CmSay( 6.1, 11.5, "Address 2", oFontText )
      oPrn:CmSay( 6.8, 11.5, "City", oFontText )
*/
         @ 5.4, 11.5 PRINT TO oPrn TEXT oBrw:Address:Value SIZE 7.0 CM FONT oFontText

     oPrn:CmBox( 8.15, 2.20, 8.75, 20.15, oPen )
     oPrn:CmSay( 8.16,  2.30, "C.I.F.:", oFontBold )
     oPrn:CmSay( 8.16,  6.00, "Invoice n�:", oFontBold )
     oPrn:CmSay( 8.16,  8.30, oBrw:InvNum:Value, oFontText )
     oPrn:CmSay( 8.16, 11.20, "Date:", oFontBold )
     oPrn:CmSay( 8.20, 12.45, DToC( oBrw:Date:Value ), oFontText )
     oPrn:CmSay( 8.16, 15.60, "PayDate:", oFontBold )
     oPrn:CmSay( 8.20, 17.50, DToC( oBrw:PayDate:Value ), oFontText )

     oPrn:CmBox( 8.90, 2.20, 9.50, 20.15, oPen )
     oPrn:CmSay ( 8.91, 2.30, "Observations:", oFontBold )

     oPrn:CmBox( 9.65, 2.20, 23.25, 20.15, oPen )
     oPrn:CmLine( 9.65, 5.20, 23.25, 5.20, oPen )
     oPrn:CmLine( 9.65, 12.20, 23.25, 12.20, oPen )
     oPrn:CmLine( 9.65, 13.80, 23.25, 13.80, oPen )
     oPrn:CmLine( 9.65, 16.10, 23.25, 16.10, oPen )
     oPrn:CmLine( 9.65, 17.10, 23.25, 17.10, oPen )
     oPrn:CmLine( 10.20, 2.20, 10.20, 20.15, oPen )

     oPrn:CmSay( 9.66,  2.30, "Code", oFontBold )
     oPrn:CmSay( 9.66,  5.30, "Description", oFontBold )
     oPrn:CmSay( 9.66, 12.30, "Quantity", oFontBold )
     oPrn:CmSay( 9.66, 14.00, "Price", oFontBold )
     oPrn:CmSay( 9.66, 16.15, "Disc", oFontBold )
     oPrn:CmSay( 9.66, 18.20, "Amount", oFontBold )

  // "INVNUM,SERIAL,ITEMCODE,ITEMNAME,QUANTITY,UNIT,PRICE,DISCOUNT,RECNO()"
  //     1      2       3       4        5       6     7      8
     for n = ( ( nPage - 1 ) * nItemsByPage ) + 1 to Min( Len( aItems ), nItemsByPage * nPage )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 3, aItems[ n ][ 3 ], oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 5.5, aItems[ n ][ 4 ], oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 12.8, AllTrim( Str( aItems[ n ][ 5 ] ) ), oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 14.5, AllTrim( Str( aItems[ n ][ 7 ] ) ), oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 16.5, AllTrim( Str( aItems[ n ][ 8 ] ) ), oFontText )
        nVal  := ROUND( aItems[ n ][ 5 ] * aItems[ n ][ 7 ] - aItems[ n ][ 8 ], 0 )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 18.5, AllTrim( Str( nVal ) ), oFontText )
     next

     oPrn:CmBox( 23.40, 2.20, 27.20, 20.15, oPen )
     oPrn:CmLine( 24.00, 2.20, 24.00, 20.15, oPen )
     oPrn:CmLine( 23.40, 4.95, 26.20, 4.95, oPen )
     oPrn:CmLine( 23.40, 6.45, 26.20, 6.45, oPen )
     oPrn:CmLine( 23.40, 9.35, 26.20, 9.35, oPen )
     oPrn:CmLine( 23.40, 10.95, 26.20, 10.95, oPen )
     oPrn:CmLine( 23.40, 13.80, 26.20, 13.80, oPen )
     oPrn:CmLine( 23.40, 16.65, 26.20, 16.65, oPen )
     oPrn:CmSay( 23.50,  2.40, "BASE", oFontBold )
     oPrn:CmSay( 23.50,   5.20, "%VAT", oFontBold )
     oPrn:CmSay( 23.50,   6.75, "CUOTE", oFontBold )
     oPrn:CmSay( 23.50,   9.60, "%RE", oFontBold )
     oPrn:CmSay( 23.50,  11.20, "CUOTE", oFontBold )
     oPrn:CmSay( 23.50,  14.10, "AMOUNT", oFontBold )
     oPrn:CmSay( 23.50, 16.95, "SUM BASES:", oFontBold )

     oPrn:CmSay( 23.50 + 1.5,  2.40, cValToStr( oBrw:Amount:Value ), oFontText )
     oPrn:CmSay( 23.50 + 1.5,  5.20, cValToStr( oBrw:TaxRate:Value ), oFontText )

     oPrn:CmSay( 26.44,  2.40, "TOTAL VAT:", oFontBold )
     oPrn:CmSay( 26.44,  5.50, cValToStr( oBrw:Tax:Value ), oFontText )
     oPrn:CmSay( 26.44,  7.70, "TOTAL R.E.:", oFontBold )
     oPrn:CmSay( 26.44, 13.35, "TOTAL INVOICE", oFontBold )
     oPrn:CmSay( 26.44, 17.50, cValToStr( oBrw:Total:Value ), oFontBold )
  ENDPAGE
   next

   ENDPRINT

   oFontTitle:End()
   oFontBold:End()
   oFontText:End()
   oPen:End()

return nil

//----------------------------------------------------------------------------//

static function OpenDataBases()  

   oCn = maria_Connect( "localhost", "fwh", "fivetec1_antonio", "1234" )  
     
if oCn == nil
MsgStop( "Error connecting to the DataBase" )
return nil
endif
return oCn //----------------------------------------------------------------------------// static function BrwBtnBar( oBrw, oWnd ) local oBar DEFINE BUTTONBAR oBar OF oWnd 2007 SIZE 70, 60 //70 DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "add" ; ACTION oBrw:EditSource( .T. ) DEFINE BUTTON OF oBar PROMPT "Edit" RESOURCE "edit" ; ACTION oBrw:EditSource() DEFINE BUTTON OF oBar PROMPT "Delete" RESOURCE "del" /* DEFINE BUTTON OF oBar PROMPT "Preview" RESOURCE "report" ; ACTION ViewInvoice( oBrw ) DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ; ACTION oWndInvoices:End() */ return oBar //----------------------------------------------------------------------------// static function BrwColors( oBrw ) local cClrBack oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW oBrw:bClrStd = { || If( oBrw:KeyNo() % 2 == 0, ; { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_BLACK ),; RGB( 198, 255, 198 ) }, ; { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_BLACK ),; RGB( 232, 255, 232 ) } ) } oBrw:bClrSel = { || { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_WHITE ),; RGB( 0x33, 0x66, 0xCC ) } } cClrBack = Eval( oBrw:bClrSelFocus )[ 2 ] oBrw:bClrSelFocus = { || { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_WHITE ),; cClrBack } } oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) ) oBrw:lHScroll := .f. return nil //----------------------------------------------------------------------------// static function BrwRecSel( oBrw, cHead ) WITH OBJECT oBrw :lFooter := .t. if "REC" $ Upper( cHead ) :bRecSelHeader := { || "RecNo" } :bRecSelData := { |o| o:BookMark } :bRecSelClick := { |o| ( o:cAlias )->( OrdSetFocus( 0 ) ), ; AEval( o:aCols, { |c| c:cOrder := "" } ), ; o:Refresh() } else :bRecSelHeader := { || "SlNo" } :bRecSelData := { |o| o:KeyNo } endif :bRecSelFooter := { |o| o:nLen } :nRecSelWidth := Replicate( '9', Len( cValToChar( Eval( oBrw:bKeyCount, oBrw ) ) ) + 1 ) END retur nil //----------------------------------------------------------------------------// static function EditItems( oRec ) local oDlg local lSave := .F. local oFont local oBtn local lAdd := ( oRec:RecNo == 0 ) DEFINE FONT oFont NAME "Tahoma" SIZE 0, -15 DEFINE DIALOG oDlg SIZE 402, 158 PIXEL FONT oFont ; TITLE If( lAdd, "New Item", "Edit Item" ) @ 12, 10 SAY "Code:" OF oDlg SIZE 19, 8 PIXEL FONT oFont @ 10, 36 GET oRec:Code OF oDlg SIZE 55, 12 PIXEL FONT oFont PICTURE "@!" UPDATE ; VALID ! Empty( oRec:Code ) @ 26, 10 SAY "Name:" OF oDlg SIZE 21, 8 PIXEL FONT oFont @ 24, 36 GET oRec:Name OF oDlg SIZE 155, 12 PIXEL FONT oFont ; VALID !Empty( oRec:Name ) UPDATE @ 40, 10 SAY "Unit:" OF oDlg SIZE 18, 8 PIXEL FONT oFont // @ 38, 36 GET oRec:Unit OF oDlg SIZE 44, 12 PIXEL FONT oFont RIGHT ; @ 38,38 COMBOBOX oRec:Unit SIZE 44,12 PIXEL OF oDlg ; ITEMS { "Items","K.G","Metre","Litre" } @ 40, 10 + 111 SAY "Price:" OF oDlg SIZE 18, 8 PIXEL FONT oFont @ 38, 36 + 111 GET oRec:Price OF oDlg SIZE 44, 12 PIXEL PICTURE "9999999.99" FONT oFont RIGHT ; VALID oRec:Price > 0 UPDATE @ 60, 111 BTNBMP oBtn PROMPT "Save" OF oDlg SIZE 42, 14 PIXEL FLAT ; WHEN oRec:Modified() ACTION (oDlg:End(), lSave := .T.) @ 60, 155 BTNBMP oBtn PROMPT "Cancel" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End()) oBtn:lCancel := .t. // oRec:bValid := { || !Duplicate( oRec:Code, "CODE", oRec:RecNo ) } ACTIVATE DIALOG oDlg CENTERED ; ON PAINT ( oDlg:Box( 10, 10, 110, 392 ) ) if lSave oRec:Save( .T. ) // Param .t. to check oRec:bValid endif return nil //----------------------------------------------------------------------------// static function EditClients( oRec ) local oDlg local lSave := .F. local oFont local oBtn local lAdd := ( oRec:RecNo == 0 ) DEFINE FONT oFont NAME "TAHOMA" SIZE 0, 15 DEFINE DIALOG oDlg SIZE 422, 326 PIXEL ; //FROM 100, 100 TO 426,522; TITLE If( lAdd, "New Client", "Edit Client" ) FONT oFont @ 12, 10 SAY "Code:" OF oDlg SIZE 19, 8 PIXEL @ 10, 46 GET oRec:Code OF oDlg SIZE 55, 12 PIXEL PICTURE "@!" UPDATE ; VALID ! Empty( oRec:Code ) @ 26, 10 SAY "First:" OF oDlg SIZE 15, 8 PIXEL @ 24, 46 GET oRec:First OF oDlg SIZE 105, 12 PIXEL UPDATE ; VALID ! Empty( oRec:First ) @ 40, 10 SAY "Last:" OF oDlg SIZE 15, 8 PIXEL @ 38, 46 GET oRec:Last OF oDlg SIZE 105, 12 PIXEL UPDATE @ 54, 10 SAY "Address1:" OF oDlg SIZE 31, 8 PIXEL @ 52, 46 GET oRec:Address1 OF oDlg SIZE 155, 12 PIXEL UPDATE @ 68, 10 SAY "Address2:" OF oDlg SIZE 31, 8 PIXEL FONT oFont @ 66, 46 GET oRec:Address2 OF oDlg SIZE 155, 12 PIXEL UPDATE @ 82, 10 SAY "City:" OF oDlg SIZE 13, 8 PIXEL @ 80, 46 GET oRec:City OF oDlg SIZE 105, 12 PIXEL UPDATE @ 96, 10 SAY "Zipcode:" OF oDlg SIZE 28, 8 PIXEL @ 94, 46 GET oRec:Zipcode OF oDlg SIZE 105, 12 PIXEL UPDATE @ 110, 10 SAY "Phone:" OF oDlg SIZE 23, 8 PIXEL @ 108, 46 GET oRec:Phone OF oDlg SIZE 105, 12 PIXEL UPDATE @ 124, 10 SAY "Email:" OF oDlg SIZE 19, 8 PIXEL @ 122, 46 GET oRec:Email OF oDlg SIZE 105, 12 PIXEL UPDATE @ 144, 121 BTNBMP oBtn PROMPT "Save" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End(), lSave := .T.) ; WHEN oRec:Modified() @ 144, 165 BTNBMP oBtn PROMPT "Cancel" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End()) oBtn:lCancel := .t. // oRec:bValid := { || !Duplicate( oRec:Code, "CODE", oRec:RecNo ) } ACTIVATE DIALOG oDlg CENTERED ; ON PAINT ( oDlg:Box( 10, 10, 278, 412 ) ) IF lSave oRec:Save( .T. ) ENDIF RETURN NIL //----------------------------------------------------------------------------// static function Duplicate( uVal, cOrder, nThisRec ) local nSaveRec := RECNO() local cSaveOrd := OrdSetFocus() local lExists := .f. DEFAULT nThisRec := nSaveRec OrdSetFocus( cOrder ) lExists := DBSEEK( uVal ) .and. RECNO() != nThisRec if ! Empty( cSaveOrd ) OrdSetFocus( cSaveOrd ) endif DBGOTO( nSaveRec ) return lExists //----------------------------------------------------------------------------// static function TableLookUp( nRow, nCol, oCol, nKey, uSource, uRetCol, aCols ) local oDlg, oBrw, uRet local aPoint local oFont, oBold local aCellCoor := oCol:oBrw:aCellCoor() DEFAULT uRetCol := 1 DEFINE FONT oFont NAME "ARIAL" SIZE 0,-12 DEFINE FONT oBold NAME "ARIAL" SIZE 0,-12 BOLD aPoint := ClientToScreen( oCol:oBrw:hWnd, { aCellCoor[ 1 ], aCellCoor[ 2 ] } ) ( uSource )->( DBSEEK( oCol:Value, .t. ), If( Eof(), DBGOBOTTOM(), nil ) ) DEFINE DIALOG oDlg SIZE 300,300 PIXEL TRUEPIXEL ; STYLE WS_POPUP OF oCol:oBrw FONT oFont ; COLOR CLR_BLACK, 1 oDlg:nSeeThroClr := 1 @ aCellCoor[ 3 ] - aCellCoor[ 1 ],0 XBROWSE oBrw SIZE 0,0 PIXEL OF oDlg ; DATASOURCE uSource AUTOCOLS ; AUTOSORT CELL LINES NOBORDER ; COLOR CLR_BLACK, RGB( 232, 255, 232 ) WITH OBJECT oBrw :lHScroll := .f. :lRecordSelector := .f. :lDrawBorder := .t. // :lIncrFilter := .t. :lSeekWild := .t. :oCol( uRetCol ):oDataFont := oBold if ValType( uSource ) == 'C' :cFilterFld := "DBRECORDINFO( 7 )" endif :bKeyDown := { |nKey| If( nKey == VK_RETURN, ( uRet := oBrw:oCol( uRetCol ):Value, oDlg:End() ), nil ) } :bKeyChar := { |nKey| If( nKey == VK_ESCAPE, ( oBrw:Seek( "" ), oDlg:End() ), nil ) } :bLDClickDatas := { || uRet := oBrw:oCol( uRetCol ):Value, oDlg:End() } :AutoFit() :CreateFromCode() END @ 00,00 SAY oBrw:oSeek PROMPT oBrw:cSeek PICTURE "@!" ; SIZE aCellCoor[ 4 ] - aCellCoor[ 2 ], aCellCoor[ 3 ] - aCellCoor[ 1 ] PIXEL OF oDlg COLOR CLR_HRED, CLR_YELLOW ; FONT oCol:DataFont WITH OBJECT oBrw:oSeek :lWantClick := .t. :bLClicked := { || oDlg:End() } END ACTIVATE DIALOG oDlg ; ON PAINT ( oDlg:Box( 0,0,20,100 ) ) ; ON INIT BrwHelpDlgInit( oBrw, aPoint ) ; VALID ( oBrw:Seek( "" ), .t. ) RELEASE FONT oFont, oBold return uRet //----------------------------------------------------------------------------// static function BrwHelpDlgInit( oBrw, aPoint ) local oDlg := oBrw:oWnd local dy := oDlg:GetRect():nWidth - oDlg:GetCliRect():nWidth local aSize aSize := oBrw:BrwFitSize() oDlg:nWidth := aSize[ 1 ] + dy oDlg:nHeight := oBrw:nTop + aSize[ 2 ] oDlg:SetPos( aPoint[ 1 ], aPoint[ 2 ] ) oDlg:Shadow() return nil //----------------------------------------------------------------------------// static function ViewInvoiceER( oBrw ) local oVRD local lPreview := .t. local cDruckerName := "" local nVal local aItems := InvItems->( ; FW_DbfToArray( nil, ; { || InvItems->INVNUM == Invoices->INVNUM } ) ) *---------------------------------------------------------- local aID_Strings := {} local aID := {} local aStrings := {} local cLogo := "" local cBezeichnung := "" local nPrintArea := 3 local n *---------------------------------------------------------- TPreview():lListViewHide := .T. EASYREPORT oVRD NAME "yinvoice\invoice.vrd" PREVIEW lPreview TO cDruckerName PRINTDIALOG IIF( lPreview, .F., .F. ) MODAL //----------------------------------------------------------------------------// //header //----------------------------------------------------------------------------// #DEFINE ER_COMPANY 201 #DEFINE ER_ADDRESS 500 #DEFINE ER_CIF 501 #DEFINE ER_INVOICE 602 #DEFINE ER_DATE 502 #DEFINE ER_PAYDATE 603 PRINTAREA 5 OF oVRD PRINTAREA 1 OF oVRD ; ITEMIDS { ER_COMPANY ,ER_ADDRESS, ER_CIF, ER_INVOICE, ER_DATE, ER_PAYDATE } ; ITEMVALUES { OBRW:CLIENT:VALUE, OBRW:ADDRESS:VALUE, "100", "220178992", DToC( oBrw:Date:Value ), DToC( oBrw:PayDate:Value ) } //----------------------------------------------------------------------------// // Data Header //----------------------------------------------------------------------------// PRINTAREA 2 OF oVRD //----------------------------------------------------------------------------// // Data //----------------------------------------------------------------------------// #DEFINE ER_CODE 200 #DEFINE ER_DESCRIPTION 201 #DEFINE ER_QUANTITY 202 #DEFINE ER_PRICE 203 #DEFINE ER_DISC 204 #DEFINE ER_AMOUNT 205 for n = 1 to Len( aItems ) PRINTAREA nPrintArea OF oVRD ; ITEMIDS { ER_CODE ,; ER_DESCRIPTION ,; ER_QUANTITY ,; ER_PRICE ,; ER_DISC ,; ER_AMOUNT } ; ITEMVALUES { aItems[ n, 3 ],; aItems[ n, 4 ],; AllTrim( Str( aItems[ n, 5 ] ) ),; AllTrim( Str( aItems[ n, 7 ] ) ),; AllTrim( Str( aItems[ n, 8 ] ) ),; AllTrim( Str( ROUND( aItems[ n, 5 ] * aItems[ n, 7 ] - aItems[ n, 8 ], 0 ) ) ) } if nPrintArea = 3 nPrintArea := 6 else nPrintArea := 3 endif next #UNDEF ER_AMOUNT //----------------------------------------------------------------------------// //Footer //----------------------------------------------------------------------------// #DEFINE ER_BASE 310 #DEFINE ER_VAT 311 #DEFINE ER_TOTALVAT 312 #DEFINE ER_TOTALINVOICE 313 PRINTAREA 4 OF oVRD ; ITEMIDS { ER_BASE ,; ER_VAT ,; ER_TOTALVAT ,; ER_TOTALINVOICE } ; ITEMVALUES { cValToStr( oBrw:Amount:Value ) ,; cValToStr( oBrw:TaxRate:Value ) ,; cValToStr( oBrw:Tax:Value ) ,; cValToStr( oBrw:Total:Value ) } oVRD:End() return nil //----------------------------------------------------------------------------// function FW_RowSetToArray( oRs, cItemFlds ) local aItems := {} oRs:GoTop() while ! oRs:Eof() AAdd( aItems,; { oRs:INVNUM, oRs:SERIAL, oRs:ITEMCODE, oRs:ITEMNAME, oRs:QUANTITY,; oRs:UNIT, oRs:PRICE, oRs:DISCOUNT, oRs:ID } ) oRs:Skip() end
return aItems //----------------------------------------------------------------------------//

Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 2:47 pm
by Antonio Linares

Enhanced version: Invoices already working :wink:

yunusm.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "easyrep.ch"

REQUEST DBFCDX

static oWndMain, oWndInvoices, oWndClients, oWndItems
static aBlankItem
static cItemFlds  := "INVNUM,SERIAL,ITEMCODE,ITEMNAME,QUANTITY,UNIT,PRICE,DISCOUNT,ID"
static nTaxRate   := 0.0
static oCn, oRsClients

//----------------------------------------------------------------------------//

function Main()

   local oBrush, oFont

   OpenDataBases()

   DEFINE BRUSH oBrush RESOURCE "background"
   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-12

//   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE WINDOW oWndMain TITLE "Invoicing" MDI MENU BuildMenu() VSCROLL HSCROLL BRUSH oBrush
   oWndMain:SetFont( oFont )

   BuildMainBar()

   DEFINE MSGBAR PROMPT "Invoicing app" ;
      OF oWndMain 2007 KEYBOARD DATE

   ACTIVATE WINDOW oWndMain MAXIMIZED

   RELEASE BRUSH oBrush

return nil

//----------------------------------------------------------------------------//

INIT PROCEDURE inv_init

   SET DATE BRITISH
   SET CENTURY ON
   SET EPOCH TO ( YEAR( DATE() ) - 50 )

   RDDSETDEFAULT( "DBFCDX" )
   SET DELETED ON

   SetGetColorFocus()

   aBlankItem := { "", 0, "", "", 0.0, "", 0.0, 0.0, 0 }

return

//----------------------------------------------------------------------------//

static function BuildMainBar()

   local oBar

   DEFINE BUTTONBAR oBar OF oWndMain 2007 SIZE 70, 60 //70

   DEFINE BUTTON OF oBar PROMPT "Invoices" RESOURCE "code" ;
      ACTION Invoices()

   DEFINE BUTTON OF oBar PROMPT "Clients" RESOURCE "clients" ;
      ACTION Clients()

   DEFINE BUTTON OF oBar PROMPT "Items" RESOURCE "relation" ;
      ACTION Items()

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End()

return nil

//----------------------------------------------------------------------------//

static function BuildMenu()

   local oMenu

   MENU oMenu

  MENUITEM "Tasks"
  MENU
     MENUITEM "Invoices" ACTION Invoices()
     //MENUITEM "Invoices items" ACTION ( "invitems" )->( XBrowse() )
     MENUITEM "Clients"  ACTION Clients()
     MENUITEM "Items"    ACTION Items()
     SEPARATOR
     MENUITEM "Exit" ACTION oWndMain:End()
  ENDMENU

  oMenu:AddMDI()
  oMenu:AddHelp( "Invoicing app", "(c) FiveTech Software" )

   ENDMENU

return oMenu

//----------------------------------------------------------------------------//

static function Clients()

   local oBrw, cClrBack, cAlias
   local oBar, oMsgBar, oMsgDeleted

   if oWndClients == nil
      oRsClients = oCn:RowSet( "SELECT * FROM clients2 ORDER BY code" )

  DEFINE WINDOW oWndClients MDICHILD OF oWndMain TITLE "Clients"

  @ 2, 0 XBROWSE oBrw OF oWndClients LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRsClients NOBORDER

  oBar  := BrwBtnBar( @oBrw, oWndClients )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION oBrw:Report( "Clients report",, .F.)

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndClients:End()

  cAlias = Alias()

  BrwColors( oBrw )
  // BrwRecSel( oBrw, "RECNO" )

  oBrw:bEdit  := { |oRec| EditClients( oRec ) }

  oBrw:CreateFromCode()
  oBrw:SetFocus()
  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }

  oWndClients:oClient = oBrw
  oWndClients:oControl = oBrw

  DEFINE MSGBAR oMsgBar OF oWndClients 2007

  ACTIVATE WINDOW oWndClients MAXIMIZED ;
     VALID ( oWndClients := nil, .T. )
   else
      oWndClients:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function Items()

   local oBrw, cClrBack
   local oBar, oMsgBar, oMsgDeleted, oRs

   if oWndItems == nil
      oRs = oCn:RowSet( "SELECT * FROM items ORDER BY code" )

  DEFINE WINDOW oWndItems MDICHILD OF oWndMain TITLE "Items"

  @ 2, 0 XBROWSE oBrw OF oWndItems LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs NOBORDER

  oBar  := BrwBtnBar( @oBrw, oWndItems )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION oBrw:Report( "Items report",, .F.)

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndItems:End()
  BrwColors( oBrw )
  // BrwRecSel( oBrw, "RECNO" )

  oBrw:bEdit  := { |oRec| EditItems( oRec ) }

  oBrw:CreateFromCode()
  oBrw:SetFocus()
  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }

  oWndItems:oClient = oBrw
  oWndItems:oControl = oBrw

  DEFINE MSGBAR oMsgBar OF oWndItems 2007

  ACTIVATE WINDOW oWndItems MAXIMIZED ;
     VALID ( oWndItems := nil, .T. )
   else
      oWndItems:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function Invoices()

   local oBrw, oChild, cClrBack, cCol
   local oBar, oMsgBar, oMsgDeleted, oRs1, oRs2

   if oWndClients == nil
      Clients()
   endif

   if oWndItems == nil
      Items()
   endif

   if oWndInvoices == nil
      oRs1 = oCn:RowSet( "SELECT * FROM invoices ORDER BY code" )
      oRs2 = oCn:RowSet( "SELECT * FROM invitems ORDER BY itemcode" )

  DEFINE WINDOW oWndInvoices MDICHILD OF oWndMain TITLE "Invoices"

  @ 60, 0 XBROWSE oBrw SIZE 0,200 PIXEL OF oWndInvoices LINES AUTOSORT ;
     AUTOCOLS DATASOURCE oRs1 NOBORDER FOOTERS

  oBar  := BrwBtnBar( @oBrw, oWndInvoices )

  DEFINE BUTTON OF oBar PROMPT "Print" RESOURCE "report" ;
     ACTION ViewInvoice( oBrw )

  DEFINE BUTTON OF oBar PROMPT "EasyReport" RESOURCE "report" ;
     ACTION ViewInvoiceER( oBrw )

  DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ;
     ACTION oWndInvoices:End()

  DEFINE MSGBAR oMsgBar OF oWndInvoices 2007

  BrwColors( oBrw )
  BrwRecSel( oBrw, "RECNO" )

  for each cCol in { "Amount", "Tax", "Total" }
     oBrw:oCol( cCol ):nFooterType  := AGGR_SUM
  next

  oBrw:bLDblClick = { || oBrw:EditSource(,, .T.) }
  oBrw:bEdit = { | oRec | EditInvoice( oRec ) }
  oBrw:MakeTotals()
  oBrw:CreateFromCode()
  oBrw:SetFocus()

  oWndInvoices:oControl = oBrw

  @ oBar:nHeight + 200,0 XBROWSE oChild SIZE 0,-oMsgBar:nHeight PIXEL OF oWndInvoices ;
     DATASOURCE oRs2 ;
     COLUMNS "ItemCode", "ItemName", "Quantity", "Unit", "Price", ;
             "ROUND(QUANTITY*PRICE,0)", "DISCOUNT","ROUND(QUANTITY*PRICE,0)-DISCOUNT" ;
     HEADERS "ItmCode", nil, nil, nil, nil, "Amount", "Discount", "Net Amount" ;
     LINES NOBORDER FOOTERS

  BrwColors( oChild )
  // BrwRecSel( oChild, "KEY" )

  for each cCol in { "Amount", "Discount", "Net Amount" }
     WITH OBJECT oChild:oCol( cCol )
        :nFooterType   := AGGR_SUM
     END
  next
  oChild:MakeTotals()
  oChild:CreateFromCode()

  oBrw:bChange   := { || oChild:Refresh(), oChild:MakeTotals(), oChild:GoTop() }

  oWndInvoices:bResized := < ||
     local oRect    := oWndInvoices:GetCliRect()
     oBrw:nHeight   := ( oRect:nHeight - oBar:nHeight - oMsgBar:nHeight ) * 0.6
     oChild:nTop    := oBrw:nTop + oBrw:nHeight
     return nil
     >

  oWndInvoices:bPostEnd   := { || oWndInvoices := nil }

  ACTIVATE WINDOW oWndInvoices MAXIMIZED

   else
      oWndInvoices:SetFocus()
   endif

return nil

//----------------------------------------------------------------------------//

static function EditInvoice( oRec )

   local lNew     := ( oRec:RecNo == 0 )
   local oDlg, oBrush, oFont, oBold, oLarge
   local oBrw, cCol, bInit, oBtn
   local aItems
   local oGetClient, cClient, bCliInit
   local nHt      := Int( ScreenHeight() * 0.8 )
   local nWd      := 1100
   local lSave    := .f., aItem

   if lNew
      oRec:Date      := Date()
      oRec:TaxRate   := nTaxRate
      oRec:InvNum    := Space( 10 )
      oRec:Code      := Space( 10 )
      aItems         := { AClone( aBlankItem ) }
   else
      aItems = FW_RowSetToArray( oCn:RowSet( "SELECT " + cItemFlds + ;
         " FROM invitems WHERE INVNUM = '" + oRec:InvNum + "' ORDER BY SERIAL" ),;
         cItemFlds )
   endif

   DEFINE BRUSH oBrush RESOURCE "PAPER"
   DEFINE FONT oLarge NAME "VERDANA" SIZE 0,-30 BOLD
   DEFINE FONT oFont NAME  "TAHOMA"  SIZE 0,-15
   DEFINE FONT oBold NAME  "TAHOMA"  SIZE 0,-15 BOLD

   DEFINE DIALOG oDlg SIZE nWd, nHt PIXEL FONT oFont TRUEPIXEL ;
      TITLE If( lNew, "NEW ", "EDIT " ) + "INVOICE" TRANSPARENT ;
      BRUSH oBrush

//   @  20, 40 SAY "INVOICE" SIZE 260,36 PIXEL OF oDlg FONT oLarge ;
   @  20, nWd/2-100 SAY "INVOICE" SIZE 200,36 PIXEL OF oDlg FONT oLarge CENTER

   @ 020, nWd - 190 GET oRec:InvNum PICTURE "@!" SIZE 150,26 PIXEL OF oDlg ;
      VALID ! Empty( oRec:InvNum )

   @ 050, nWd - 190 GET oRec:Date   SIZE 150,26 PIXEL OF oDlg RIGHT ;
                  ACTION oRec:Date := Min( MsgDate( oRec:Date ), Date() )

   @  80-60, 40 SAY "Client:" SIZE 100,24 PIXEL OF oDlg

   @  80-60,150 GET oGetClient VAR oRec:Code SIZE 150,26 PIXEL OF oDlg ;
         ACTION ( PopupBrowse( oRsClients, oGetClient ), ;
                  ReadClientInfo( oRec, oDlg ) ) ;
         VALID ( ReadClientInfo( oRec, oDlg ) )

   @ 125-60, 60 SAY oRec:Client SIZE 200,24 PIXEL OF oDlg FONT oBold UPDATE
   @ 150-60, 60 SAY oRec:Address SIZE 200, 60 PIXEL OF oDlg UPDATE

   @ 180-60,310 SAY "Text :" SIZE 100,24 PIXEL OF oDlg
   @ 204-60,310 GET oRec:Details SIZE nWd-310-40,26 PIXEL OF oDlg UPDATE

   @ 240-60,040 XBROWSE oBrw SIZE -40,-150+45 PIXEL OF oDlg ;
      DATASOURCE aItems ;
      COLUMNS 3,4,5,6,7,8 ;
      HEADERS "ITEM", "DETAILS", "QTY", "UNIT","PRICE","DISCOUNT" ;
      PICTURES "@!", nil, "9999.999", nil, "999.99", "999,999,999" ;
      COLSIZES nil, 30 ;
      CELL LINES NOBORDER FASTEDIT FOOTERS

   ADD TO oBrw AT 6 HEADER "AMOUNT" DATA ROUND( oBrw:aRow[5] * oBrw:aRow[7], 0 ) ;
      PICTURE "999,999,999"

   ADD TO oBrw HEADER "NET" DATA ROUND( oBrw:aRow[5] * oBrw:aRow[7] - oBrw:aRow[ 8 ], 0 ) ;
      PICTURE "999,999,999"

   for each cCol in { "amount", "discount", "net" }
      WITH OBJECT oBrw:oCol( cCol )
         :nFooterType   := AGGR_SUM
      END
   next

   for each cCol in { "qty", "price", "discount" }
      WITH OBJECT oBrw:oCol( cCol )
         :nEditType     := EDIT_GET
         :bEditValid    := { |o| o:VarGet() >= 0 }
         :bOnChange     := { || oBrw:MakeTotals( { "amount", "net" } ), oBrw:RefreshFooters(), oDlg:Update() }
      END
   next

   for each cCol in { "details", "unit", "amount", "net" }
      oBrw:oCol( cCol ):bClrStd  := { || { CLR_BLACK, RGB( 240, 240, 240 ) } }
   next

   // AutoAppendCode
   WITH OBJECT oBrw
      :AddVar( "AAPPEND", nil )
      :bClrStd    := { || If( oBrw:aRow == oBrw:aAppend, { CLR_BLACK, CLR_YELLOW }, { CLR_BLACK, oBrw:nClrPane } ) }

  :bChange    := { || If( oBrw:nArrayAt < oBrw:nLen, CheckAppendRow( oBrw ), nil ) }

  :bPastEof   := { || If( oBrw:aAppend != nil .and. Empty( oBrw:aAppend[ 3 ] ), nil, ;
           ( AAdd( oBrw:aArrayData, oBrw:aAppend := AClone( aBlankItem ) ), ;
             oBrw:GoBottom(), oBrw:GoLeftMost(), oBrw:RefreshCurrent(), ;
             oBrw:MakeTotals(), oBrw:Refresh() ) ) }

  :bKeyDown   := { |k| If( k == VK_DELETE, ( oBrw:aAppend := nil, oBrw:Delete(), 0 ), nil ) }

   END

   WITH OBJECT oBrw:aCols[ 1 ]
      :nEditType     = EDIT_BUTTON
      :bEditBlock    = { | nRow, nCol, oCol, nKey | TableLookUp( nRow, nCol, oCol, nKey, "ITEMS" ) }
      :bOnChange     = { || oBrw:aAppend := nil, ReadItemInfo( oBrw:aRow, oBrw ), oBrw:RefreshCurrent(), ;
                            oBrw:MakeTotals(), oBrw:RefreshFooters(), oDlg:Update() }
   END

   WITH OBJECT oBrw
      :lFlatStyle    := .t.
      :nStretchCol   := 2
      :lHScroll      := .f.
      :bOnRefresh    := { || oDlg:Update() }
      //
      BrwRecSel( oBrw, "KEYNO" )
      //
      :MakeTotals()
      :CreateFromCode()
   END

   @ nHt - 139 + 45, nWd - 380 SAY "TAX @" ;
      SIZE 80,24 PIXEL OF oDlg RIGHT

   @ nHt - 140 + 45, nWd - 280 GET oRec:TaxRate PICTURE "99.99 %" ;
      SIZE 100,26 PIXEL OF oDlg RIGHT ;
      VALID ( If( oRec:TaxRate >= 0, ( oDlg:Update(), .t. ), .f. ) )

   @ nHT - 139 + 45, nWd - 170 SAY ;
      ( oRec:Tax := ROUND( oBrw:Net:nTotal * oRec:TaxRate / 100, 0 ) ) ;
      PICTURE "999,999,999" SIZE 105,24 PIXEL OF oDlg UPDATE RIGHT

   @ nHt - 105 + 45, nWd - 270 SAY "TOTAL" SIZE 80, 24 PIXEL OF oDlg RIGHT

   @ nHt - 105 + 45, nWd - 170 SAY ;
      ( oRec:Total := oBrw:Net:nTotal + oRec:Tax ) ;
      PICTURE "999,999,999" SIZE 105, 24 PIXEL OF oDlg UPDATE RIGHT

/*
   @ nHt - 60, nWd - 260 BTNBMP PROMPT "Save"  SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION ( lSave := .t., oDlg:End() )

   @ nHt - 60, nWd - 140 BTNBMP oBtn PROMPT "Cancel" SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION oDlg:End()
   oBtn:lCancel   := .t.
*/
   @ nHt - 60, 040 BTNBMP PROMPT "Save"  SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION ( lSave := .t., oDlg:End() )

   @ nHt - 60, 160 BTNBMP oBtn PROMPT "Cancel" SIZE 100,30 PIXEL OF oDlg FLAT ;
      ACTION oDlg:End()
   oBtn:lCancel   := .t.



   ACTIVATE DIALOG oDlg CENTERED ;
      ON PAINT (  oDlg:Box( 110-60, 40, 230-60, 300 ), ;
                  oDlg:Line( nHt - 112 + 45, nWd - 170, nHt - 112 + 45, nWd - 55 ), ;
                  oDlg:Line( nHt -  78 + 45, nWd - 170, nHt -  78 + 45, nWd - 55 ), ;
                  oDlg:Line( nHt -  75 + 45, nWd - 170, nHt -  75 + 45, nWd - 55 )  )

   if lSave
      CheckAppendRow( oBrw )
      if Empty( aItems ) .or. Empty( oRec:InvNum ) .or. Empty( oRec:Code ) .or. oRec:Total <= 0
      else

     oRec:Amount    := oBrw:Net:nTotal

     if ! Empty( oBrw:aDeleted )
        for each aItem in oBrw:aDeleted
           oCn:Execute( "DELETE FROM invitems WHERE id = " + Str( ABS( aItem[9] ) ) )
        next
     endif
     AEval( aItems, { |a| a[ 1 ] := oRec:InvNum } )
     AEval( aItems, { |a,i| a[ 2 ] := i } )
     for each aItem in aItems
        oCn:Execute( "INSERT INTO invitems (invnum, serial, itemcode, itemname, quantity, unit, price, discount) VALUES ('" + aItem[1] + "', " + Str(aItem[2]) + ", '" + Str( aItem[3] ) + "', '" + aItem[4] + "', " + Str(aItem[5]) + ", '" + aItem[6] + "', " + Str(aItem[7]) + ", " + Str(aItem[8]) + ") ON DUPLICATE KEY UPDATE itemname = VALUES(itemname), quantity = VALUES(quantity), unit = VALUES(unit), price = VALUES(price), discount = VALUES(discount)" )
     next
     oRec:Save()
     WITH OBJECT oRec:oBrw
        :MakeTotals()
        :RefreshFooters()
        Eval( :bChange, oRec:oBrw )
     END
  endif

   endif

   RELEASE FONT oFont, oLarge
   RELEASE BRUSH oBrush

return nil

//----------------------------------------------------------------------------//

static function CheckAppendRow( oBrw, aAppend )

   if Empty( ATail( oBrw:aArrayData )[ 3 ] )
      ASize( oBrw:aArrayData, oBrw:nLen - 1 )
      oBrw:aAppend  := nil
      oBrw:Refresh()
   endif

return nil

//----------------------------------------------------------------------------//

static function ReadClientInfo( oRec, oDlg )

   local oRs := oCn:RowSet( "SELECT first, last, address1, address2, city, zipcode FROM clients2 WHERE code = '" + oRec:Code + "'" )
   local lValid   := .f.
   local aRet := {}

   if oRs:RecCount > 0
      oRs:GoTop()
      oRec:Client    := TRIM( oRs:FIRST ) + " " + TRIM( oRs:LAST )
      if ! Empty( oRs:ADDRESS1 ); AAdd( aRet, TRIM( oRs:ADDRESS1 ) ); endif
      if ! Empty( oRs:ADDRESS2 ); AAdd( aRet, TRIM( oRs:ADDRESS2 ) ); endif
      if ! Empty( oRs:CITY ); AAdd( aRet, TRIM( oRs:CITY ) + " " + TRIM( oRs:ZIPCODE ) ); endif
      oRec:Address   := If( Empty( aRet ), "", FW_ArrayAsList( aRet, CRLF ) )
      lValid         := .t.
   endif

   if oDlg != nil
      oDlg:Update()
   endif

return lValid

//----------------------------------------------------------------------------//

static function PickAddress()

   local aRet  := {}

   if ! Empty( FIELD->ADDRESS1 ); AAdd( aRet, TRIM( FIELD->ADDRESS1 ) ); endif
   if ! Empty( FIELD->ADDRESS2 ); AAdd( aRet, TRIM( FIELD->ADDRESS2 ) ); endif
   if ! Empty( FIELD->CITY ); AAdd( aRet, TRIM( FIELD->CITY ) + " " + TRIM( FIELD->ZIPCODE ) ); endif

   if Empty( aRet )
      return ""
   endif

return FW_ArrayAsList( aRet, CRLF )

static function ReadItemInfo( aRow, oBrw )

   local oRs := oCn:RowSet( "SELECT name, unit, price FROM items WHERE code = '" + AllTrim( Str( aRow[ 3 ] ) ) + "'" )
   local lValid   := .f.

   if oRs:RecCount > 0
      oRs:GoTop()
      aRow[ 4 ]      := TRIM( oRs:NAME )
      if aRow[ 5 ] == 0
         aRow[ 5 ]   := 1
      endif
      aRow[ 6 ]      := oRs:UNIT
      aRow[ 7 ]      := oRs:PRICE
      lValid         := .t.
   endif

   if oBrw != nil
      oBrw:RefreshCurrent()
      oBrw:MakeTotals()
      oBrw:oWnd:Update()
   endif

return lValid

//----------------------------------------------------------------------------//

static function ViewInvoice( oBrw )

   local oPrn, oFontTitle, oFontBold, oFontText, oPen, n
   local nVal, nPage, nItemsByPage := 10
   local aItems := FW_RowSetToArray( oCn:RowSet( "SELECT " + cItemFlds + ;
      " FROM invitems WHERE INVNUM = '" + ;
      oBrw:InvNum:Value + "' ORDER BY SERIAL" ), cItemFlds )

   PRINT oPrn NAME "INVOICE" PREVIEW

   DEFINE FONT oFontTitle NAME "Arial" SIZE 0, -19 BOLD OF oPrn
   DEFINE FONT oFontBold  NAME "Arial" SIZE 0, -12 BOLD OF oPrn
   DEFINE FONT oFontText  NAME "Arial" SIZE 0, -12 OF oPrn
   DEFINE PEN oPen WIDTH 2

   for nPage = 1 to ( Len( aItems ) / nItemsByPage ) + 1
      PAGE
         oPrn:CmSay( 3.1, 2.3, "Company Name", oFontTitle )

     oPrn:CmBox( 4.4, 10.9, 7.7, 20.15, oPen )
     oPrn:CmSay( 4.7, 11.5, oBrw:Client:Value, oFontBold )
/*
      oPrn:CmSay( 5.4, 11.5, "Address 1", oFontText )
      oPrn:CmSay( 6.1, 11.5, "Address 2", oFontText )
      oPrn:CmSay( 6.8, 11.5, "City", oFontText )
*/
         @ 5.4, 11.5 PRINT TO oPrn TEXT oBrw:Address:Value SIZE 7.0 CM FONT oFontText

     oPrn:CmBox( 8.15, 2.20, 8.75, 20.15, oPen )
     oPrn:CmSay( 8.16,  2.30, "C.I.F.:", oFontBold )
     oPrn:CmSay( 8.16,  6.00, "Invoice n�:", oFontBold )
     oPrn:CmSay( 8.16,  8.30, oBrw:InvNum:Value, oFontText )
     oPrn:CmSay( 8.16, 11.20, "Date:", oFontBold )
     oPrn:CmSay( 8.20, 12.45, DToC( oBrw:Date:Value ), oFontText )
     oPrn:CmSay( 8.16, 15.60, "PayDate:", oFontBold )
     oPrn:CmSay( 8.20, 17.50, DToC( oBrw:PayDate:Value ), oFontText )

     oPrn:CmBox( 8.90, 2.20, 9.50, 20.15, oPen )
     oPrn:CmSay ( 8.91, 2.30, "Observations:", oFontBold )

     oPrn:CmBox( 9.65, 2.20, 23.25, 20.15, oPen )
     oPrn:CmLine( 9.65, 5.20, 23.25, 5.20, oPen )
     oPrn:CmLine( 9.65, 12.20, 23.25, 12.20, oPen )
     oPrn:CmLine( 9.65, 13.80, 23.25, 13.80, oPen )
     oPrn:CmLine( 9.65, 16.10, 23.25, 16.10, oPen )
     oPrn:CmLine( 9.65, 17.10, 23.25, 17.10, oPen )
     oPrn:CmLine( 10.20, 2.20, 10.20, 20.15, oPen )

     oPrn:CmSay( 9.66,  2.30, "Code", oFontBold )
     oPrn:CmSay( 9.66,  5.30, "Description", oFontBold )
     oPrn:CmSay( 9.66, 12.30, "Quantity", oFontBold )
     oPrn:CmSay( 9.66, 14.00, "Price", oFontBold )
     oPrn:CmSay( 9.66, 16.15, "Disc", oFontBold )
     oPrn:CmSay( 9.66, 18.20, "Amount", oFontBold )

  // "INVNUM,SERIAL,ITEMCODE,ITEMNAME,QUANTITY,UNIT,PRICE,DISCOUNT,RECNO()"
  //     1      2       3       4        5       6     7      8
     for n = ( ( nPage - 1 ) * nItemsByPage ) + 1 to Min( Len( aItems ), nItemsByPage * nPage )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 3, aItems[ n ][ 3 ], oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 5.5, aItems[ n ][ 4 ], oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 12.8, AllTrim( Str( aItems[ n ][ 5 ] ) ), oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 14.5, AllTrim( Str( aItems[ n ][ 7 ] ) ), oFontText )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 16.5, AllTrim( Str( aItems[ n ][ 8 ] ) ), oFontText )
        nVal  := ROUND( aItems[ n ][ 5 ] * aItems[ n ][ 7 ] - aItems[ n ][ 8 ], 0 )
        oPrn:CmSay( 9.66 + n - ( ( nPage - 1 ) * nItemsByPage ), 18.5, AllTrim( Str( nVal ) ), oFontText )
     next

     oPrn:CmBox( 23.40, 2.20, 27.20, 20.15, oPen )
     oPrn:CmLine( 24.00, 2.20, 24.00, 20.15, oPen )
     oPrn:CmLine( 23.40, 4.95, 26.20, 4.95, oPen )
     oPrn:CmLine( 23.40, 6.45, 26.20, 6.45, oPen )
     oPrn:CmLine( 23.40, 9.35, 26.20, 9.35, oPen )
     oPrn:CmLine( 23.40, 10.95, 26.20, 10.95, oPen )
     oPrn:CmLine( 23.40, 13.80, 26.20, 13.80, oPen )
     oPrn:CmLine( 23.40, 16.65, 26.20, 16.65, oPen )
     oPrn:CmSay( 23.50,  2.40, "BASE", oFontBold )
     oPrn:CmSay( 23.50,   5.20, "%VAT", oFontBold )
     oPrn:CmSay( 23.50,   6.75, "CUOTE", oFontBold )
     oPrn:CmSay( 23.50,   9.60, "%RE", oFontBold )
     oPrn:CmSay( 23.50,  11.20, "CUOTE", oFontBold )
     oPrn:CmSay( 23.50,  14.10, "AMOUNT", oFontBold )
     oPrn:CmSay( 23.50, 16.95, "SUM BASES:", oFontBold )

     oPrn:CmSay( 23.50 + 1.5,  2.40, cValToStr( oBrw:Amount:Value ), oFontText )
     oPrn:CmSay( 23.50 + 1.5,  5.20, cValToStr( oBrw:TaxRate:Value ), oFontText )

     oPrn:CmSay( 26.44,  2.40, "TOTAL VAT:", oFontBold )
     oPrn:CmSay( 26.44,  5.50, cValToStr( oBrw:Tax:Value ), oFontText )
     oPrn:CmSay( 26.44,  7.70, "TOTAL R.E.:", oFontBold )
     oPrn:CmSay( 26.44, 13.35, "TOTAL INVOICE", oFontBold )
     oPrn:CmSay( 26.44, 17.50, cValToStr( oBrw:Total:Value ), oFontBold )
  ENDPAGE
   next

   ENDPRINT

   oFontTitle:End()
   oFontBold:End()
   oFontText:End()
   oPen:End()

return nil

//----------------------------------------------------------------------------//

static function OpenDataBases()  

   oCn = maria_Connect( "localhost", "fwh", "fivetec1_antonio", "1234" )  
     
if oCn == nil
MsgStop( "Error connecting to the DataBase" )
return nil
endif
return oCn //----------------------------------------------------------------------------// static function BrwBtnBar( oBrw, oWnd ) local oBar DEFINE BUTTONBAR oBar OF oWnd 2007 SIZE 70, 60 //70 DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "add" ; ACTION oBrw:EditSource( .T. ) DEFINE BUTTON OF oBar PROMPT "Edit" RESOURCE "edit" ; ACTION oBrw:EditSource() DEFINE BUTTON OF oBar PROMPT "Delete" RESOURCE "del" /* DEFINE BUTTON OF oBar PROMPT "Preview" RESOURCE "report" ; ACTION ViewInvoice( oBrw ) DEFINE BUTTON OF oBar PROMPT "Close" RESOURCE "exit" ; ACTION oWndInvoices:End() */ return oBar //----------------------------------------------------------------------------// static function BrwColors( oBrw ) local cClrBack oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW oBrw:bClrStd = { || If( oBrw:KeyNo() % 2 == 0, ; { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_BLACK ),; RGB( 198, 255, 198 ) }, ; { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_BLACK ),; RGB( 232, 255, 232 ) } ) } oBrw:bClrSel = { || { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_WHITE ),; RGB( 0x33, 0x66, 0xCC ) } } cClrBack = Eval( oBrw:bClrSelFocus )[ 2 ] oBrw:bClrSelFocus = { || { If( ( oBrw:cAlias )->( Deleted() ), CLR_HRED, CLR_WHITE ),; cClrBack } } oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) ) oBrw:lHScroll := .f. return nil //----------------------------------------------------------------------------// static function BrwRecSel( oBrw, cHead ) WITH OBJECT oBrw :lFooter := .t. if "REC" $ Upper( cHead ) :bRecSelHeader := { || "RecNo" } :bRecSelData := { |o| o:BookMark } :bRecSelClick := { |o| ( o:cAlias )->( OrdSetFocus( 0 ) ), ; AEval( o:aCols, { |c| c:cOrder := "" } ), ; o:Refresh() } else :bRecSelHeader := { || "SlNo" } :bRecSelData := { |o| o:KeyNo } endif :bRecSelFooter := { |o| o:nLen } :nRecSelWidth := Replicate( '9', Len( cValToChar( Eval( oBrw:bKeyCount, oBrw ) ) ) + 1 ) END retur nil //----------------------------------------------------------------------------// static function EditItems( oRec ) local oDlg local lSave := .F. local oFont local oBtn local lAdd := ( oRec:RecNo == 0 ) DEFINE FONT oFont NAME "Tahoma" SIZE 0, -15 DEFINE DIALOG oDlg SIZE 402, 158 PIXEL FONT oFont ; TITLE If( lAdd, "New Item", "Edit Item" ) @ 12, 10 SAY "Code:" OF oDlg SIZE 19, 8 PIXEL FONT oFont @ 10, 36 GET oRec:Code OF oDlg SIZE 55, 12 PIXEL FONT oFont PICTURE "@!" UPDATE ; VALID ! Empty( oRec:Code ) @ 26, 10 SAY "Name:" OF oDlg SIZE 21, 8 PIXEL FONT oFont @ 24, 36 GET oRec:Name OF oDlg SIZE 155, 12 PIXEL FONT oFont ; VALID !Empty( oRec:Name ) UPDATE @ 40, 10 SAY "Unit:" OF oDlg SIZE 18, 8 PIXEL FONT oFont // @ 38, 36 GET oRec:Unit OF oDlg SIZE 44, 12 PIXEL FONT oFont RIGHT ; @ 38,38 COMBOBOX oRec:Unit SIZE 44,12 PIXEL OF oDlg ; ITEMS { "Items","K.G","Metre","Litre" } @ 40, 10 + 111 SAY "Price:" OF oDlg SIZE 18, 8 PIXEL FONT oFont @ 38, 36 + 111 GET oRec:Price OF oDlg SIZE 44, 12 PIXEL PICTURE "9999999.99" FONT oFont RIGHT ; VALID oRec:Price > 0 UPDATE @ 60, 111 BTNBMP oBtn PROMPT "Save" OF oDlg SIZE 42, 14 PIXEL FLAT ; WHEN oRec:Modified() ACTION (oDlg:End(), lSave := .T.) @ 60, 155 BTNBMP oBtn PROMPT "Cancel" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End()) oBtn:lCancel := .t. // oRec:bValid := { || !Duplicate( oRec:Code, "CODE", oRec:RecNo ) } ACTIVATE DIALOG oDlg CENTERED ; ON PAINT ( oDlg:Box( 10, 10, 110, 392 ) ) if lSave oRec:Save( .T. ) // Param .t. to check oRec:bValid endif return nil //----------------------------------------------------------------------------// static function EditClients( oRec ) local oDlg local lSave := .F. local oFont local oBtn local lAdd := ( oRec:RecNo == 0 ) DEFINE FONT oFont NAME "TAHOMA" SIZE 0, 15 DEFINE DIALOG oDlg SIZE 422, 326 PIXEL ; //FROM 100, 100 TO 426,522; TITLE If( lAdd, "New Client", "Edit Client" ) FONT oFont @ 12, 10 SAY "Code:" OF oDlg SIZE 19, 8 PIXEL @ 10, 46 GET oRec:Code OF oDlg SIZE 55, 12 PIXEL PICTURE "@!" UPDATE ; VALID ! Empty( oRec:Code ) @ 26, 10 SAY "First:" OF oDlg SIZE 15, 8 PIXEL @ 24, 46 GET oRec:First OF oDlg SIZE 105, 12 PIXEL UPDATE ; VALID ! Empty( oRec:First ) @ 40, 10 SAY "Last:" OF oDlg SIZE 15, 8 PIXEL @ 38, 46 GET oRec:Last OF oDlg SIZE 105, 12 PIXEL UPDATE @ 54, 10 SAY "Address1:" OF oDlg SIZE 31, 8 PIXEL @ 52, 46 GET oRec:Address1 OF oDlg SIZE 155, 12 PIXEL UPDATE @ 68, 10 SAY "Address2:" OF oDlg SIZE 31, 8 PIXEL FONT oFont @ 66, 46 GET oRec:Address2 OF oDlg SIZE 155, 12 PIXEL UPDATE @ 82, 10 SAY "City:" OF oDlg SIZE 13, 8 PIXEL @ 80, 46 GET oRec:City OF oDlg SIZE 105, 12 PIXEL UPDATE @ 96, 10 SAY "Zipcode:" OF oDlg SIZE 28, 8 PIXEL @ 94, 46 GET oRec:Zipcode OF oDlg SIZE 105, 12 PIXEL UPDATE @ 110, 10 SAY "Phone:" OF oDlg SIZE 23, 8 PIXEL @ 108, 46 GET oRec:Phone OF oDlg SIZE 105, 12 PIXEL UPDATE @ 124, 10 SAY "Email:" OF oDlg SIZE 19, 8 PIXEL @ 122, 46 GET oRec:Email OF oDlg SIZE 105, 12 PIXEL UPDATE @ 144, 121 BTNBMP oBtn PROMPT "Save" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End(), lSave := .T.) ; WHEN oRec:Modified() @ 144, 165 BTNBMP oBtn PROMPT "Cancel" OF oDlg SIZE 42, 14 PIXEL FLAT ACTION (oDlg:End()) oBtn:lCancel := .t. // oRec:bValid := { || !Duplicate( oRec:Code, "CODE", oRec:RecNo ) } ACTIVATE DIALOG oDlg CENTERED ; ON PAINT ( oDlg:Box( 10, 10, 278, 412 ) ) IF lSave oRec:Save( .T. ) ENDIF RETURN NIL //----------------------------------------------------------------------------// static function Duplicate( uVal, cOrder, nThisRec ) local nSaveRec := RECNO() local cSaveOrd := OrdSetFocus() local lExists := .f. DEFAULT nThisRec := nSaveRec OrdSetFocus( cOrder ) lExists := DBSEEK( uVal ) .and. RECNO() != nThisRec if ! Empty( cSaveOrd ) OrdSetFocus( cSaveOrd ) endif DBGOTO( nSaveRec ) return lExists //----------------------------------------------------------------------------// static function TableLookUp( nRow, nCol, oCol, nKey, uSource, uRetCol, aCols ) local oDlg, oBrw, uRet local aPoint local oFont, oBold local aCellCoor := oCol:oBrw:aCellCoor() local oRs DEFAULT uRetCol := 1 DEFINE FONT oFont NAME "ARIAL" SIZE 0,-12 DEFINE FONT oBold NAME "ARIAL" SIZE 0,-12 BOLD aPoint := ClientToScreen( oCol:oBrw:hWnd, { aCellCoor[ 1 ], aCellCoor[ 2 ] } ) oRs = oCn:RowSet( "SELECT * FROM " + Lower(uSource) + " ORDER BY code" ) DEFINE DIALOG oDlg SIZE 300,300 PIXEL TRUEPIXEL ; STYLE WS_POPUP OF oCol:oBrw FONT oFont ; COLOR CLR_BLACK, 1 oDlg:nSeeThroClr := 1 @ aCellCoor[ 3 ] - aCellCoor[ 1 ],0 XBROWSE oBrw SIZE 0,0 PIXEL OF oDlg ; DATASOURCE oRs AUTOCOLS ; AUTOSORT CELL LINES NOBORDER ; COLOR CLR_BLACK, RGB( 232, 255, 232 ) WITH OBJECT oBrw :lHScroll := .f. :lRecordSelector := .f. :lDrawBorder := .t. // :lIncrFilter := .t. :lSeekWild := .t. :oCol( uRetCol ):oDataFont := oBold :bKeyDown := { |nKey| If( nKey == VK_RETURN, ( uRet := oBrw:oCol( uRetCol ):Value, oDlg:End() ), nil ) } :bKeyChar := { |nKey| If( nKey == VK_ESCAPE, ( oBrw:Seek( "" ), oDlg:End() ), nil ) } :bLDClickDatas := { || uRet := oBrw:oCol( uRetCol ):Value, oDlg:End() } :AutoFit() :CreateFromCode() :Seek( oCol:Value ) END @ 00,00 SAY oBrw:oSeek PROMPT oBrw:cSeek PICTURE "@!" ; SIZE aCellCoor[ 4 ] - aCellCoor[ 2 ], aCellCoor[ 3 ] - aCellCoor[ 1 ] PIXEL OF oDlg COLOR CLR_HRED, CLR_YELLOW ; FONT oCol:DataFont WITH OBJECT oBrw:oSeek :lWantClick := .t. :bLClicked := { || oDlg:End() } END ACTIVATE DIALOG oDlg ; ON PAINT ( oDlg:Box( 0,0,20,100 ) ) ; ON INIT BrwHelpDlgInit( oBrw, aPoint ) ; VALID ( oBrw:Seek( "" ), .t. ) RELEASE FONT oFont, oBold return uRet //----------------------------------------------------------------------------// static function BrwHelpDlgInit( oBrw, aPoint ) local oDlg := oBrw:oWnd local dy := oDlg:GetRect():nWidth - oDlg:GetCliRect():nWidth local aSize aSize := oBrw:BrwFitSize() oDlg:nWidth := aSize[ 1 ] + dy oDlg:nHeight := oBrw:nTop + aSize[ 2 ] oDlg:SetPos( aPoint[ 1 ], aPoint[ 2 ] ) oDlg:Shadow() return nil //----------------------------------------------------------------------------// static function ViewInvoiceER( oBrw ) local oVRD local lPreview := .t. local cDruckerName := "" local nVal local aItems := FW_RowSetToArray( oCn:RowSet( "SELECT " + cItemFlds + " FROM invitems WHERE INVNUM = '" + oBrw:InvNum:Value + "' ORDER BY SERIAL" ), cItemFlds ) *---------------------------------------------------------- local aID_Strings := {} local aID := {} local aStrings := {} local cLogo := "" local cBezeichnung := "" local nPrintArea := 3 local n *---------------------------------------------------------- TPreview():lListViewHide := .T. EASYREPORT oVRD NAME "yinvoice\invoice.vrd" PREVIEW lPreview TO cDruckerName PRINTDIALOG IIF( lPreview, .F., .F. ) MODAL //----------------------------------------------------------------------------// //header //----------------------------------------------------------------------------// #DEFINE ER_COMPANY 201 #DEFINE ER_ADDRESS 500 #DEFINE ER_CIF 501 #DEFINE ER_INVOICE 602 #DEFINE ER_DATE 502 #DEFINE ER_PAYDATE 603 PRINTAREA 5 OF oVRD PRINTAREA 1 OF oVRD ; ITEMIDS { ER_COMPANY ,ER_ADDRESS, ER_CIF, ER_INVOICE, ER_DATE, ER_PAYDATE } ; ITEMVALUES { OBRW:CLIENT:VALUE, OBRW:ADDRESS:VALUE, "100", "220178992", DToC( oBrw:Date:Value ), DToC( oBrw:PayDate:Value ) } //----------------------------------------------------------------------------// // Data Header //----------------------------------------------------------------------------// PRINTAREA 2 OF oVRD //----------------------------------------------------------------------------// // Data //----------------------------------------------------------------------------// #DEFINE ER_CODE 200 #DEFINE ER_DESCRIPTION 201 #DEFINE ER_QUANTITY 202 #DEFINE ER_PRICE 203 #DEFINE ER_DISC 204 #DEFINE ER_AMOUNT 205 for n = 1 to Len( aItems ) PRINTAREA nPrintArea OF oVRD ; ITEMIDS { ER_CODE ,; ER_DESCRIPTION ,; ER_QUANTITY ,; ER_PRICE ,; ER_DISC ,; ER_AMOUNT } ; ITEMVALUES { aItems[ n, 3 ],; aItems[ n, 4 ],; AllTrim( Str( aItems[ n, 5 ] ) ),; AllTrim( Str( aItems[ n, 7 ] ) ),; AllTrim( Str( aItems[ n, 8 ] ) ),; AllTrim( Str( ROUND( aItems[ n, 5 ] * aItems[ n, 7 ] - aItems[ n, 8 ], 0 ) ) ) } if nPrintArea = 3 nPrintArea := 6 else nPrintArea := 3 endif next #UNDEF ER_AMOUNT //----------------------------------------------------------------------------// //Footer //----------------------------------------------------------------------------// #DEFINE ER_BASE 310 #DEFINE ER_VAT 311 #DEFINE ER_TOTALVAT 312 #DEFINE ER_TOTALINVOICE 313 PRINTAREA 4 OF oVRD ; ITEMIDS { ER_BASE ,; ER_VAT ,; ER_TOTALVAT ,; ER_TOTALINVOICE } ; ITEMVALUES { cValToStr( oBrw:Amount:Value ) ,; cValToStr( oBrw:TaxRate:Value ) ,; cValToStr( oBrw:Tax:Value ) ,; cValToStr( oBrw:Total:Value ) } oVRD:End() return nil //----------------------------------------------------------------------------// function FW_RowSetToArray( oRs, cItemFlds ) local aItems := {} oRs:GoTop() while ! oRs:Eof() AAdd( aItems,; { oRs:INVNUM, oRs:SERIAL, oRs:ITEMCODE, oRs:ITEMNAME, oRs:QUANTITY,; oRs:UNIT, oRs:PRICE, oRs:DISCOUNT, oRs:ID } ) oRs:Skip() end
return aItems //----------------------------------------------------------------------------//

Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 3:06 pm
by Antonio Linares

FWH samples yunus.prg working with MariaDb :D

Image


Re: Unicode GET cannot be highlighted

Posted: Thu Nov 27, 2025 6:14 pm
by Antonio Linares

Regarding your unicode GET question here you have a fine working example with FWH 25.09:

Code: Select all | Expand

#include "FiveWin.ch"

function Main()

local oDlg, cVar := "中国版 (China)"

FW_SetUnicode( .T. )

DEFINE DIALOG oDlg 

@ 2, 2 GET cVar 

ACTIVATE DIALOG oDlg CENTERED 

return nil