Página 1 de 1

Harbour, xHarbour, compatibilidade

Enviado: 11 Jan 2017 09:31
por JoséQuintas
Eu sempre achei que usar a biblioteca de compatibilidade com xHarbour poderia ser problema.
Um motivo simples: se é pra Harbour funcionar igual xHarbour, ele não vai funcionar do jeito que deveria.

Ontem um programador estava com problemas ao usar a classe Sefaz.
Aplicativo com automação Word.

Ao acrescentar a Sefaz, a automacão Word não funcionava.
Retirando a Sefaz, a automação Word funcionava normalmente.

Automação Word usando TOleAuto():New()
Sefaz usando win_OleCreateObject()

TOleAuto():New() faz parte da biblioteca de compatibilidade com xHarbour.
Ao usar wapi_OleCreateObject() também pra Word, tudo resolvido.

Então... cuidado com a biblioteca de compatibilidade com xHarbour.

Isso reforça outra coisa que venho mencionando:
As bibliotecas costumam manter compatibilidade com Harbour e xHarbour.
Com isso, podem existir exemplos das duas formas.
E acabamos tendo esse problema, usando exemplos da própria LIB.

Isso pode explicar muitos problemas que alguns usários tem ao testar exemplos, que funciona em um lugar e em outro não.

NÃO é bug na LIB de compatibilidade xHarbour.
A LIB foi criada para que o Harbour se comporte igual xHarbour, e os fontes xHarbour funcionem.
Ela faz o que foi feita pra fazer.

Então, melhor evitar ao máximo o uso da biblioteca de compatibilidade, se possível eliminar o seu uso.
E cuidado com LIBs compatíveis com Harbour/xHarbour, elas podem conter "armadilhas" deste tipo.
Duas funções que separadamente funcionam, mas juntas causam problema.

Este é o primeiro caso confirmado sobre isso, que tenho conhecimento.
Não faço idéia se existem outras situações semelhantes.

Nota:
O programador em questão estava usando minigui, e usou exemplo que veio na minigui.
Se a minigui funciona em Harbour e xHarbour, o exemplo está correto.... pelo menos pra xHarbour, ou pra Harbour sem usar as duas funções juntas.

Harbour, xHarbour, compatibilidade

Enviado: 09 Fev 2017 10:13
por Linguagemclipper
Qual é o nome dessa biblioteca de compatibilidade e onde posso baixar?
Atualmente qual compilador é mais recomendável? O xHarbour ou Harbour?

Harbour, xHarbour, compatibilidade

Enviado: 09 Fev 2017 10:51
por JoséQuintas
A biblioteca vém com o Harbour.

O que já foi muito falado:
o xHarbour é internamente diferente do Harbour, já havia algumas diferenças importantes de funcionamento..
Começaram a copiar rotinas do Harbour para o xHarbour, sem os devidos ajustes.
Se for fazer uso avançado, pode ter surpresas.

O X era porque se tratava de um Harbour considerado mais avançado, não restrito ao padrão Clipper, e com mais recursos.
Atualmente, acho que a coisa se inverteu.

Então o recomendado é Harbour.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 16:00
por Linguagemclipper
Descobrí uma função que deveria ser copiada do xHarbour para o Harbour: TBROWSE.PRG
Eu queria migrar do xHarbour para Harbour, mas ainda bem que descobrí que meu sistema ficou bugado a tempo.
O comportamento do TBROWSE é diferente!!!
No Harbour o COLPOS não pula para a próxima coluna que está além das colunas mostradas na tela.
Decidí olhar no código fonte de ambos e descobrí que é problema no fonte mesmo. Vejamos:

O método SetColPos no Harbour é muito pequeno e simples, vejamos:

Código: Selecionar todos

METHOD setColPos( nColPos ) CLASS TBrowse

   IF ::nConfigure != 0
      ::doConfigure()
   ENDIF

   IF HB_ISNUMERIC( nColPos )
      ::nColPos := nColPos
   ELSE
      ::nColPos := 0
   ENDIF

   RETURN ::nColPos
Enquanto que, esse método lá no xHarbour é bem mais completo e aborda exatamente essa questão, vejamos:

Código: Selecionar todos

*------------------------------------------------------*
METHOD SetColPos( nColPos ) CLASS TBrowse
*------------------------------------------------------*

   default nColPos to 0

   if ::lNeverDisplayed .OR. (! ::lStable .AND. nColPos <= ::nRightVisible .AND. nColPos >= ::nLeftVisible)
      return ::nColPos := nColPos

   elseif nColPos <> 0 .AND. nColPos <> ::nColPos

      ::Moved()

      // I'm still inside columns currently shown
      if nColPos <= ::nRightVisible  .AND.;
         nColPos >= Max( ::nLeftVisible, ::nFrozenCols )

         ::nColPos := nColpos

      else
         // moving to the right
         if nColPos > ::nColPos

            if nColPos <= ::nColCount

               ::nRightVisible := nColPos
               ::nLeftVisible := ::LeftDetermine()
               ::nColPos := nColPos

            endif

         // moving to the left
         else

            if nColPos >= 1

               // Until the leftmost column has a number higher than the column I want to reach
               while ::nLeftVisible > nColPos

                  ::nRightVisible--
                  ::nLeftVisible := ::LeftDetermine()

               enddo

               ::nColPos := nColPos

            endif

         endif

         ::Invalidate()

      endif

      ::ForceStable()

   endif

Return ::nColPos
Se alguém souber mandar um pedido de atualização pra eles, seria uma boa consertar isso. Daí eu já poderia usar o Harbour para meu programa.
Criei um issue lá: https://github.com/harbour/core/issues/264

Acabei de ver que você fez um fork lá do tbrowse: tbrowse heading/column/footer separator color #185
Será que você não poderia ajudar nessa questão? Mandar um fork e pull request desse SetColPos aí pra lá?

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 16:17
por Itamar M. Lins Jr.
Olá!
seria uma boa consertar isso.
Quebra compatibilidade com CLIPPER ? Não é um BUG pq se fosse já teriam consertado, haja vista ter muito mais usuários do Harbour que do xHarbour.
Até o Patrick Mast tá lá siscando... Quer dizer (salvo engano) nem xHarbour dele ele usa mais.
Imagem

Saudações,
Itamar M. Lins Jr.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 16:32
por Itamar M. Lins Jr.
Olá!
Não basta "apenas" colocar o código.
Tem variáveis que não existem. Por exemplo lNeverDisplayed não existe no Harbour.
É melhor pegar o fonte do xHarbour e usar no seu sistema.
Pq pode quebrar compatibilidade com alguma LIB WVG por exemplo.
Olhei agora o código dos dois, e definitivamente o do Harbour foi todo reescrito. Não tem nada a ver com o do xHarbour.

Saudações,
Itamar M. Lins Jr.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 16:41
por Itamar M. Lins Jr.
Olá!
No Harbour o COLPOS não pula para a próxima coluna que está além das colunas mostradas na tela.
Tem como demonstrar isso ?
Postar aqui no forum um exemplo bem pequeno para nós testarmos ?

Saudações,
Itamar M. Lins Jr.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 16:42
por JoséQuintas
Outras opções:

1) Cria sua própria tbrowse pra ser compilada no aplicativo

2) Faz um fork do Harbour, altera só o seu, se quiser deixar no harbour mesmo

Já usei as duas alternativas.
E o seu fork continuará podendo ser atualizado semi-automaticamente normalmente.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 16:46
por Itamar M. Lins Jr.
Olá!
Aqui pula para próxima coluna.
Teste ai Quintas para ver se pula(scroll). Ele disse que o browse() cheio de fields,(maior que a tela) não faz o scroll horizontal. Pelo menos foi isso que entendi.

Saudações,
Itamar M. Lins Jr.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 18:09
por JoséQuintas
Scroll horizontal eu uso.

O que ele diz é sobre usar aquela variável pra isso.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 19:00
por Linguagemclipper
Gravei um vídeo para demonstrar o mesmo sistema compilado em Harbour e em xHarbour para demonstrar o comportamento diferente do TBROWSE:
[youtube]https://youtu.be/hhXzvo6OA7Y[/youtube]
https://youtu.be/hhXzvo6OA7Y

Minha função é muito grande (quase 2000 linhas), mas essa parte aí é basicamente um loop da coluna 1 ou 2 (variável nCOL) até a última coluna.
No xHarbour as colunas são empurradas normalmente para a esquerda, enquanto que, no Harbour esbarra na última coluna mostrada na tela.

Código: Selecionar todos

FOR T=nCOL TO LEN(aDADOS)
   oTBR:COLPOS := T
   // código para preencher os GETs
NEXT
Esse COLPOS aí vai chamar aquele método setColPos

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 21:50
por Itamar M. Lins Jr.
Olá!
Eu vi.
Infelizmente eu não uso mais tbrowse.
Mas no meu sistema antigo, rodava de boa isso ai.
Acredito que a solução do problema e vc reescrever seu código.
Um exemplo pequeno não é complicado de fazer para mostrar exatamente como vc faz. No caso eu uso Hwgui.

Saudações,
Itamar M. Lins Jr.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 22:32
por Linguagemclipper
Fiz um teste mais simplificado e acho que o erro está no READ porque ele trabalha com o MESSAGE e acaba mudando a posição do cursor. Essa mudança do cursor atrapalha algumas vezes, é intermitente.
Pode fazer o teste aí tirando o SETPOS(nROW,nCOL), esse código abaixo está completo, pode compilar direto.

Código: Selecionar todos

/*┌───────────────────────────────────────────┐
  │ WEBSITE     : www.linguagemclipper.com.br │
  │ PROGRAMADOR : ANDERSON CARDOSO SILVA      │
  └───────────────────────────────────────────┘ */
FUNCTION MAIN()
#INCLUDE "INKEY.CH"
LOCAL aWst
LOCAL lExt

SET COLOR TO W+/N
SET SCOREBOARD OFF
SET DATE BRITISH
SET EPOCH TO 1980
SET MESSAGE TO 23
SETMODE(25,80)

*** DEFINIR IDIOMA PORTUGUÊS ***
REQUEST HB_CODEPAGE_PT850 &&& PARA INDEXAR CAMPOS ACENTUADOS
HB_SETCODEPAGE("PT850")   &&& PARA INDEXAR CAMPOS ACENTUADOS
// No Harbour deve compilar com: xhb.hbc
 
CLS
cT1 = "EXEMPLO BÁSICO DE FUNCIONAMENTO DO TBROWSE"
cT2 := "Tecle [ESC] para sair"
cT3 := "www.linguagemclipper.com.br"
@ 00,(80-LEN(cT1))/2 SAY cT1
@ 23,(80-LEN(cT2))/2 SAY cT2
@ 24,(80-LEN(cT3))/2 SAY cT3
 
// CRIACAO DBFs E NTXs.
IF !FILE("PESSOAS.DBF")
   aDBF_EM := {}
   AADD(aDBF_EM, { "NOME",       "C", 35, 0 })
   AADD(aDBF_EM, { "NASC",       "D",  8, 2 })
   AADD(aDBF_EM, { "FONE",       "C", 11, 0 })
   AADD(aDBF_EM, { "CIDADE",     "C", 15, 0 })  
   AADD(aDBF_EM, { "UF",         "C",  2, 0 })
   DBCREATE("PESSOAS", aDBF_EM)
   USE PESSOAS ALIAS PE EXCLUSIVE NEW
   INDEX ON NOME TO PESSOAS
   PE->( DBCLOSEAREA())
ELSE
	USE PESSOAS ALIAS PE EXCLUSIVE NEW
	SET INDEX TO PESSOAS
ENDIF
 
cCOLOR = SETCOLOR()
// CRIA OBJETO TBROWSE oTBRX C/ CODEBLOCKS PADRÕES
SET COLOR TO W+/B
@ 04,09 TO 20,71 DOUBLE
oTBRX := TBrowseDB(05,10,20,70)
 
// MONTA COLUNAS DOS DADOS DESEJADOS C/ O OBJETO TBCOLUMN
// ATRIBUI OS TÍTULOS E VALORES DOS CAMPOS DE CADA COLUNA
// Criamos um objeto TBColumnNew() e o inserimos no objeto TBrowse() com addcolumn()
oTBRX:addcolumn( tbcolumnNew( "NOME",     {|| PE->NOME}   ))  // COLUNA 1
oTBRX:addcolumn( tbcolumnNew( "DT. NASC", {|| PE->NASC}   ))  // COLUNA 2
oTBRX:addcolumn( tbcolumnNew( "FONE",     {|| PE->FONE}   ))  // COLUNA 3
oTBRX:addcolumn( tbcolumnNew( "CIDADE",   {|| PE->CIDADE} ))  // COLUNA 4
oTBRX:addcolumn( tbcolumnNew( "UF",       {|| PE->UF}     ))  // COLUNA 5
 
// COMO FORMATAR UMA COLUNA COM UMA MÁSCARA
oTCOL := oTBRX:GETCOLUMN(3)            // PEGA OBJETO DA COLUNA DESEJADA, A 3
oTCOL:PICTURE := "@R (99) 99999-9999"  // FORMATA A COLUNA COM A MÁSCARA 
 
oTBRX:HeadSep := CHR(205) + CHR(203) + CHR(205)    // ═╦═ SEPARADOR DE CABECALHO
oTBRX:ColSep  := " "+chr(186)+" "                  //  ║  SEPARADOR DE COLUNAS
oTBRX:FootSep := CHR(205) + CHR(202) + CHR(205)    // ═╩═ SEPARADOR DE RODAPE
 
 
// NAVEGACAO E CONTROLE DA TABELA
lExt := .F.
DO WHILE !lExt
 
      IF !oTBRX:STABLE
         *** ATUALIZACAO DO TBROWSE
         IF INDEXORD() = 0 
            // BANCO DE DADOS NÃO ESTÁ INDEXADO
            oTBRX:REFRESHCURRENT()    
         ELSE
            // BANCO DE DADOS ESTÁ INDEXADO
            oTBRX:REFRESHALL()        
         ENDIF
         DO WHILE !oTBRX:STABILIZE()
         ENDDO
      ENDIF
 
	  aWSt := INKEY(0) // ESPERA UMA TECLA
 
      DO CASE       // manipulação padrão de teclas de navegação
         CASE aWst == K_DOWN          ; oTBRX:down()
         CASE aWst == K_UP            ; oTBRX:up()
         CASE aWst == K_PGDN          ; oTBRX:pageDown()
         CASE aWst == K_PGUP          ; oTBRX:pageUp()
         CASE aWst == K_CTRL_PGUP     ; oTBRX:goTop()
         CASE aWst == K_CTRL_PGDN     ; oTBRX:goBottom()
         CASE aWst == K_RIGHT         ; oTBRX:right()
         CASE aWst == K_LEFT          ; oTBRX:left()
         CASE aWst == K_HOME          ; oTBRX:home()
         CASE aWst == K_END           ; oTBRX:end()
         CASE aWst == K_CTRL_LEFT     ; oTBRX:panLeft()
         CASE aWst == K_CTRL_RIGHT    ; oTBRX:panRight()
         CASE aWst == K_CTRL_HOME     ; oTBRX:panHome()
         CASE aWst == K_CTRL_END      ; oTBRX:panEnd()
         CASE aWst == K_ESC           ; lExt := .T. // SAIR
         CASE aWst == K_INS          
				// Teclou [Insert]
				// Rotina para inserir registros
				PE->(DBAPPEND())
				FOR T=1 TO oTBRX:colCount
					oTBRX:COLPOS := T
					oTBRX:REFRESHALL()            
					IF !oTBRX:STABLE
						DO WHILE !oTBRX:STABILIZE()
						ENDDO
					ENDIF
					xVAR := oTBRX:getColumn( oTBRX:COLPOS )
					bCB  := xVAR:BLOCK                      // CODEBLOCK da coluna TBrowse
					xVAL := EVAL( bCB )                     // RESULTADO DO CODEBLOCK
					nROW := ROW()
					nCOL := COL()
					@ ROW(),COL() GET xVAL
					READ    // READ estava mudando a posição do cursor! 
							// Provavelmente por conta de um eventual MESSAGE
					SETPOS(nROW,nCOL)  // AQUI RESOLVEU
					// OBS: AS 2 LINHAS ABAIXO FUNCIONAM PORQUE A ORDEM DOS CAMPOS NO DBF
					// É IGUAL À ORDEM DOS CAMPOS NO TBROWSE, OU SEJA, oTBRX:COLPOS = FIELDNUM().
					xFIELD   := "PE->" + FIELDNAME( oTBRX:COLPOS )					
					&xFIELD. := xVAL
				NEXT

         CASE aWst == K_ENTER        
              // Teclou [Enter]
              // Rotina para editar registros
			  		xVAR := oTBRX:getColumn( oTBRX:COLPOS ) // PEGA O OBJETO TBCOLUMN
					bCB  := xVAR:BLOCK                      // CODEBLOCK da coluna TBrowse
					xVAL := EVAL( bCB )                     // RESULTADO DO CODEBLOCK
					
					nROW := ROW()
					nCOL := COL()					
					@ ROW(),COL() GET xVAL
					READ    // READ estava mudando a posição do cursor! 
							// Provavelmente por conta de um eventual MESSAGE
					SETPOS(nROW,nCOL) // RESOLVE ASSIM
					// OBS: AS 2 LINHAS ABAIXO FUNCIONAM PORQUE A ORDEM DOS CAMPOS NO DBF
					// É IGUAL À ORDEM DOS CAMPOS NO TBROWSE, OU SEJA, oTBRX:COLPOS = FIELDNUM().
					xFIELD   := "PE->" + FIELDNAME( oTBRX:COLPOS )
					&xFIELD. := xVAL					
         CASE aWst == K_DEL          
              // Teclou [Delete]
              // Rotina para deletar registros
				PE->(DBDELETE())
				PACK
			  	oTBRX:REFRESHALL()            
				IF !oTBRX:STABLE
					DO WHILE !oTBRX:STABILIZE()
					ENDDO
				ENDIF
         OTHERWISE
              // QUALQUER OUTRA TECLA
         ENDCASE
ENDDO
SET COLOR TO
CLS
RETURN
Também quebrei a cabeça para obter o nome do campo que está em xVAR:BLOCK, mas não conseguí. Se pudesse converter o codeblock em string daria para trabalhar com os campos que quisesse do banco de dados nesse exemplo aí ao invés de todos os campos porque daria para usar o FIELDNUM() ou FIELDPOS() com o FIELDGET() e FIELDPUT().
Eu criei uma função para resolver um monte de coisa com o tbrowse e nela não tenho esse problema. Vou testar essa parada do SETPOS() após o READ para ver se resolve lá também ao compilar com o Harbour.

Harbour, xHarbour, compatibilidade

Enviado: 21 Jul 2022 22:58
por Linguagemclipper
Olha o que eu acabei de achar lá entre as linhas 64 e 67 do fonte do Harbour https://github.com/harbour/core/blob/ma ... getsys.prg:

Código: Selecionar todos

   IF Empty( GetList )
      SetPos( MaxRow() - 1, 0 )
      RETURN .F.
   ENDIF
É justamente no maxrow()-1 que o campo vai parar!...
Achei que fosse por conta do MESSAGE, mas GELIST fica vazia após o READ, correto?

Harbour, xHarbour, compatibilidade

Enviado: 22 Jul 2022 12:11
por Linguagemclipper
Descobrí o problema:

1) Precisava estabilizar o TBROWSE após alterar o :COLPOS
Normal, mas no xHarbour estava funcionando sem fazer isso.
Agora o TBROWSE já puxa para a esquerda a tabela normalmente.

Código: Selecionar todos

FOR T=nCOL TO LEN(aDADOS)
       oTBR:COLPOS := T
// [...]
       // NECESSÁRIO NO HARBOUR PARA ATUALIZAR O :COLPOS
       oTBR:REFRESHCURRENT() // SOLICITA ATUALIZACAO TBROWSE
       oTBR:FORCESTABLE()    // ATUALIZA TBROWSE
// [...]
2) Precisava salvar a posição do cursor para restaurar depois do READ

Código: Selecionar todos

               nROW := ROW()
               nCOL := COL()               
               @ ROW(),COL() GET xVAL
               READ    // READ estava mudando a posição do cursor! 
                     // Provavelmente por conta de um eventual MESSAGE
               SETPOS(nROW,nCOL) // RESOLVE ASSIM
O problema que ficou agora é que sempre que vou inserir um registro novo o Harbour joga os velhos para cima limpando a tabela e deixa o registro novo na primeira linha, enquanto que, no xHarbour ele deixa os registros velhos onde estão e só faz descer para a última linha para preencher o registro novo.

Imagem
Em Harbour à esquerda e xHarbour à direita.
Obs.: A dispensa nº 002/2021 tem vários registros como na dispensa nº 003/2021.