From 882b41f195c375feb1b6b81923e2db2c9bf2cec3 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Fri, 16 Nov 2007 00:38:52 +0000 Subject: [PATCH] 2007-11-16 01:25 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) + contrib/freeimage + contrib/freeimage/Makefile + contrib/freeimage/make_b32.bat + contrib/freeimage/make_vc.bat + contrib/freeimage/common.mak + contrib/freeimage/freeimage.ch + contrib/freeimage/fi_winfu.c + contrib/freeimage/fi_wrp.c + contrib/freeimage/readme.txt + contrib/freeimage/test + contrib/freeimage/test/bld_b32.bat + contrib/freeimage/test/fitest.prg + contrib/freeimage/test/sample1.jpg + contrib/freeimage/test/italia.gif + contrib/freeimage/test/fsg.jpg + contrib/freeimage/test/images_out + Added FreeImage OSS library Harbour interface. ! Some minor fixes and file rearrangements made. + Added std make files. ; TOFIX: There is still a potentially dangerous warning to be fixed in FI_GETBACKGROUNDCOLOR() ; Borrowed from xhb. ; NOTE: The lib made some features available through the xhb specific C struct functionality. Since such functionality is not implemented in Harbour, the library would need to be extened with some more wrappers to make C level vars accessible from Harbour code. But even without this functionality, the lib seems quite useful. ; NOTE: The lib also has some Windows specific + contrib/xhb/hbfast.h + Added this file to enhance C interface code compatibility with xhb. * contrib/firebird/* ! Fixed SVN properties. --- harbour/ChangeLog | 38 + harbour/contrib/firebird/Makefile | 34 +- harbour/contrib/firebird/common.mak | 36 +- harbour/contrib/firebird/firebird.c | 1474 +++++----- harbour/contrib/firebird/make_b32.bat | 2 +- harbour/contrib/firebird/make_vc.bat | 2 +- harbour/contrib/firebird/readme.txt | 108 +- harbour/contrib/firebird/test/Makefile | 64 +- harbour/contrib/firebird/test/bld_b32.bat | 2 +- harbour/contrib/firebird/test/simple.prg | 376 +-- harbour/contrib/firebird/test/stress.prg | 268 +- harbour/contrib/firebird/test/test.prg | 154 +- harbour/contrib/firebird/test/testapi.c | 806 +++--- harbour/contrib/firebird/tfirebird.prg | 2126 +++++++-------- harbour/contrib/freeimage/Makefile | 15 + harbour/contrib/freeimage/common.mak | 18 + harbour/contrib/freeimage/fi_winfu.c | 245 ++ harbour/contrib/freeimage/fi_wrp.c | 2877 ++++++++++++++++++++ harbour/contrib/freeimage/freeimage.ch | 337 +++ harbour/contrib/freeimage/make_b32.bat | 79 + harbour/contrib/freeimage/make_vc.bat | 95 + harbour/contrib/freeimage/readme.txt | 58 + harbour/contrib/freeimage/test/bld_b32.bat | 80 + harbour/contrib/freeimage/test/fitest.prg | 242 ++ harbour/contrib/freeimage/test/fsg.jpg | Bin 0 -> 1706 bytes harbour/contrib/freeimage/test/italia.gif | Bin 0 -> 21287 bytes harbour/contrib/freeimage/test/sample1.jpg | Bin 0 -> 63809 bytes harbour/contrib/xhb/hbfast.h | 5 + 28 files changed, 6815 insertions(+), 2726 deletions(-) create mode 100644 harbour/contrib/freeimage/Makefile create mode 100644 harbour/contrib/freeimage/common.mak create mode 100644 harbour/contrib/freeimage/fi_winfu.c create mode 100644 harbour/contrib/freeimage/fi_wrp.c create mode 100644 harbour/contrib/freeimage/freeimage.ch create mode 100644 harbour/contrib/freeimage/make_b32.bat create mode 100644 harbour/contrib/freeimage/make_vc.bat create mode 100644 harbour/contrib/freeimage/readme.txt create mode 100644 harbour/contrib/freeimage/test/bld_b32.bat create mode 100644 harbour/contrib/freeimage/test/fitest.prg create mode 100644 harbour/contrib/freeimage/test/fsg.jpg create mode 100644 harbour/contrib/freeimage/test/italia.gif create mode 100644 harbour/contrib/freeimage/test/sample1.jpg create mode 100644 harbour/contrib/xhb/hbfast.h diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3831b73ef1..139e0429f7 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,44 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2007-11-16 01:25 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) + + contrib/freeimage + + contrib/freeimage/Makefile + + contrib/freeimage/make_b32.bat + + contrib/freeimage/make_vc.bat + + contrib/freeimage/common.mak + + contrib/freeimage/freeimage.ch + + contrib/freeimage/fi_winfu.c + + contrib/freeimage/fi_wrp.c + + contrib/freeimage/readme.txt + + contrib/freeimage/test + + contrib/freeimage/test/bld_b32.bat + + contrib/freeimage/test/fitest.prg + + contrib/freeimage/test/sample1.jpg + + contrib/freeimage/test/italia.gif + + contrib/freeimage/test/fsg.jpg + + contrib/freeimage/test/images_out + + Added FreeImage OSS library Harbour interface. + ! Some minor fixes and file rearrangements made. + + Added std make files. + ; TOFIX: There is still a potentially dangerous + warning to be fixed in FI_GETBACKGROUNDCOLOR() + ; Borrowed from xhb. + ; NOTE: The lib made some features available through the xhb + specific C struct functionality. Since such functionality + is not implemented in Harbour, the library would need + to be extened with some more wrappers to make C level + vars accessible from Harbour code. But even without + this functionality, the lib seems quite useful. + ; NOTE: The lib also has some Windows specific + + + contrib/xhb/hbfast.h + + Added this file to enhance C interface code compatibility + with xhb. + + * contrib/firebird/* + ! Fixed SVN properties. + 2007-11-15 20:44 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) + contrib/firebird + contrib/firebird/Makefile diff --git a/harbour/contrib/firebird/Makefile b/harbour/contrib/firebird/Makefile index 9ddd1fe990..4b5bb19a56 100644 --- a/harbour/contrib/firebird/Makefile +++ b/harbour/contrib/firebird/Makefile @@ -1,17 +1,17 @@ -# -# $Id: Makefile 4853 2001-12-25 16:51:58Z lculik $ -# - -ROOT = ../../ - -CFLAGS += -I/opt/firebird/include - -C_SOURCES=\ - firebird.c \ - -PRG_SOURCES=\ - tfirebird.prg \ - -LIBNAME=firebird - -include $(TOP)$(ROOT)config/lib.cf +# +# $Id$ +# + +ROOT = ../../ + +CFLAGS += -I/opt/firebird/include + +C_SOURCES=\ + firebird.c \ + +PRG_SOURCES=\ + tfirebird.prg \ + +LIBNAME=firebird + +include $(TOP)$(ROOT)config/lib.cf diff --git a/harbour/contrib/firebird/common.mak b/harbour/contrib/firebird/common.mak index 5b8f4e905c..9beda8a7b2 100644 --- a/harbour/contrib/firebird/common.mak +++ b/harbour/contrib/firebird/common.mak @@ -1,18 +1,18 @@ -# -# $Id: common.mak 7935 2007-11-10 11:31:17Z vszakats $ -# - -LIBNAME = firebird - -LIB_PATH = $(LIB_DIR)\$(LIBNAME)$(LIBEXT) - -# -# LIB rules -# - -LIB_OBJS = \ - $(OBJ_DIR)\firebird$(OBJEXT) \ - $(OBJ_DIR)\tfirebird$(OBJEXT) \ - -all: \ - $(LIB_PATH) \ +# +# $Id$ +# + +LIBNAME = firebird + +LIB_PATH = $(LIB_DIR)\$(LIBNAME)$(LIBEXT) + +# +# LIB rules +# + +LIB_OBJS = \ + $(OBJ_DIR)\firebird$(OBJEXT) \ + $(OBJ_DIR)\tfirebird$(OBJEXT) \ + +all: \ + $(LIB_PATH) \ diff --git a/harbour/contrib/firebird/firebird.c b/harbour/contrib/firebird/firebird.c index fa3ec8a0ee..170f88e871 100644 --- a/harbour/contrib/firebird/firebird.c +++ b/harbour/contrib/firebird/firebird.c @@ -1,737 +1,737 @@ -/* - * $Id: atrepl.c 7583 2007-07-06 21:17:36Z druzus $ - */ - -/* - * xHarbour Project source code: - * Firebird RDBMS low level (client api) interface code. - * - * Copyright 2003 Rodrigo Moreno rodrigo_moreno@yahoo.com - * www - http://www.xharbour.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). - * - * As a special exception, the Harbour Project gives permission for - * additional uses of the text contained in its release of Harbour. - * - * The exception is that, if you link the Harbour libraries with other - * files to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the Harbour library code into it. - * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. - * - * This exception applies only to the code released by the Harbour - * Project under the name Harbour. If you copy code from other - * Harbour Project or Free Software Foundation releases into a copy of - * Harbour, as the General Public License permits, the exception does - * not apply to the code that you add in this way. To avoid misleading - * anyone as to the status of such modified files, you must delete - * this exception notice from them. - * - * If you write modifications of your own for Harbour, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. - * - * See doc/license.txt for licensing terms. - * - */ - -#define _CLIPDEFS_H -#if defined(HB_OS_WIN_32_USED) - #include -#endif - -#include -#include -#include -#include - -#include "extend.api" -#include "item.api" -#include "hbapiitm.h" -#include "ibase.h" - -#define DIALECT 1 -#define MAX_FIELDS 5 -#define MAX_LEN 256 -#define MAX_BUFFER 1024 - -#define ERREXIT(status) { _retnl(isc_sqlcode(status)); return; } - -#ifndef ISC_INT64_FORMAT - -#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__BORLANDC__) && defined(__WIN32__)) -#define ISC_INT64_FORMAT "I64" -#else -#define ISC_INT64_FORMAT "ll" -#endif -#endif - -HB_FUNC(FBCREATEDB) -{ - isc_db_handle newdb = NULL; - isc_tr_handle trans = NULL; - long status[20]; - char create_db[MAX_BUFFER]; - - char *db_name; - char *user; - char *pass; - char *charset; - int page; - int dialect; - - if (hb_pcount() != 6) - { - _retni(0); - return; - } - - db_name = hb_parcx(1); - user = hb_parcx(2); - pass = hb_parcx(3); - page = hb_parni(4); - charset = hb_parcx(5); - dialect = hb_parni(6); - - sprintf(create_db, - "CREATE DATABASE '%s' USER '%s' PASSWORD '%s' PAGE_SIZE = %i DEFAULT CHARACTER SET %s", - db_name, user, pass, page, charset ); - - if (isc_dsql_execute_immediate(status, &newdb, &trans, 0, create_db, dialect, NULL)) - ERREXIT(status); - - _retni(1); -} - - -HB_FUNC(FBCONNECT) -{ - ISC_STATUS status[MAX_FIELDS]; - isc_db_handle db = NULL; - char *db_connect = NULL; - char *user = NULL; - char *passwd = NULL; - char dpb[128]; - int i = 0, len; - - PHB_ITEM db_handle; - - if (hb_parinfo(1)) - db_connect = hb_parcx(1); - - if (hb_parinfo(2)) - user = hb_parcx(2); - - if (hb_parinfo(3)) - passwd = hb_parcx(3); - - dpb[i++] = isc_dpb_version1; - - dpb[i++] = isc_dpb_user_name; - len = strlen(user); - dpb[i++] = (char) len; - strncpy(&(dpb[i]), user, len); - i += len; - - dpb[i++] = isc_dpb_password; - len = strlen (passwd); - dpb[i++] = len; - strncpy(&(dpb[i]), passwd, len); - i += len; - - if ( isc_attach_database ( status, 0, db_connect, &db, i, dpb ) ) - ERREXIT(status); - - db_handle = hb_itemPutPtr( NULL, ( void * ) db ); - _itemReturn(db_handle); - _itemRelease(db_handle); -} - - -HB_FUNC(FBCLOSE) -{ - isc_db_handle db = NULL; - long status[20]; - - db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - - if ( isc_detach_database ( status, &db ) ) - ERREXIT(status); - - _retnl(1); -} - - -HB_FUNC(FBERROR) -{ - int sqlcode; - char msg[MAX_BUFFER]; - - sqlcode = hb_parni(1); - - isc_sql_interprete(sqlcode, msg, 512); - - _retc(msg); -} - -HB_FUNC(FBSTARTTRANSACTION) -{ - isc_db_handle db = NULL; - isc_tr_handle trans = NULL; - long status[MAX_FIELDS]; - - PHB_ITEM var; - - db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - - if (isc_start_transaction(status, &trans, 1, &db, 0, NULL)) - ERREXIT(status); - - var = hb_itemPutPtr( NULL, ( void * ) trans ); - _itemReturn(var); - _itemRelease(var); -} - - -HB_FUNC(FBCOMMIT) -{ - isc_tr_handle trans = NULL; - long status[MAX_FIELDS]; - - trans = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - - if (isc_commit_transaction(status, &trans)) - ERREXIT(status); - - trans = NULL; - _retnl(1); -} - -HB_FUNC(FBROLLBACK) -{ - isc_tr_handle trans = NULL; - long status[MAX_FIELDS]; - - trans = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - - if (isc_rollback_transaction(status, &trans)) - ERREXIT(status); - - trans = NULL; - _retnl(1); -} - - -HB_FUNC(FBEXECUTE) -{ - isc_db_handle db = NULL; - isc_tr_handle trans = NULL; - char *exec_str; - long status[20]; - long status_rollback[20]; - int dialect; - - db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - exec_str = hb_parcx(2); - dialect = hb_parni(3); - - if (hb_parinfo(4)) { - trans = (isc_tr_handle) hb_itemGetPtr( hb_param( 4, HB_IT_POINTER ) ); - } else { - if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) - ERREXIT(status); - } - - if (isc_dsql_execute_immediate(status, &db, &trans, 0, exec_str, dialect, NULL)) { - if (! hb_parinfo(4)) - isc_rollback_transaction ( status_rollback, &trans ); - - ERREXIT(status); - } - - if (!hb_parinfo(4)) - if ( isc_commit_transaction ( status, &trans ) ) - ERREXIT(status); - - _retnl(1); -} - -HB_FUNC(FBQUERY) -{ - isc_db_handle db = NULL; - isc_tr_handle trans = NULL; - ISC_STATUS status[MAX_FIELDS]; - XSQLDA ISC_FAR * sqlda; - isc_stmt_handle stmt = NULL; - XSQLVAR *var; - - char sel_str[MAX_LEN]; - int dialect; - int n, i, dtype; - int num_cols; - - ITEM qry_handle; - ITEM temp; - ITEM aTemp; - ITEM aNew; - - ITEM itemSqlname; - ITEM itemSqltype; - ITEM itemSqllen ; - ITEM itemSqlscale; - ITEM itemRelname; - - db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - strcpy(sel_str, hb_parcx(2)); - - if (hb_parinfo(3)) { - dialect = hb_parni(3); - } else { - dialect = DIALECT; - } - - if (hb_parinfo(4)) { - trans = (isc_tr_handle) hb_itemGetPtr( hb_param( 4, HB_IT_POINTER ) ); - - } else if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) - ERREXIT(status); - - // Allocate an output SQLDA. Just to check number of columns - sqlda = ( XSQLDA * ) hb_xgrab( XSQLDA_LENGTH ( 1 ) ); - sqlda->sqln = 1; - sqlda->version = 1; - - // Allocate a statement - if (isc_dsql_allocate_statement(status, &db, &stmt)) - ERREXIT(status); - - // Prepare the statement. - if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, dialect, sqlda)) - ERREXIT(status); - - // Describe sql contents - if (isc_dsql_describe(status, &stmt, dialect, sqlda)) - ERREXIT(status); - - num_cols = sqlda->sqld; - aNew = _itemArrayNew( num_cols ); - - // Relocate necessary number of columns - if ( sqlda->sqld > sqlda->sqln ) { - hb_xfree( sqlda ); - n = sqlda->sqld; - sqlda = ( XSQLDA * ) hb_xgrab( XSQLDA_LENGTH ( n ) ); - sqlda->sqln = n; - sqlda->version = 1; - - if (isc_dsql_describe(status, &stmt, dialect, sqlda)) - ERREXIT(status); - } - - for ( i = 0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++ ) { - dtype = ( var->sqltype & ~1 ); - switch ( dtype ) { - case SQL_VARYING: - var->sqltype = SQL_TEXT; - var->sqldata = ( char * ) hb_xgrab( sizeof ( char ) * var->sqllen + 2 ); - break; - case SQL_TEXT: - var->sqldata = ( char * ) hb_xgrab( sizeof ( char ) * var->sqllen + 2 ); - break; - case SQL_LONG: - var->sqltype = SQL_LONG; - var->sqldata = ( char * ) hb_xgrab( sizeof ( long ) ); - break; - default: - var->sqldata = ( char * ) hb_xgrab( sizeof ( char ) * var->sqllen ); - break; - } - if ( var->sqltype & 1 ) { - var->sqlind = ( short * ) hb_xgrab( sizeof ( short ) ); - } - - aTemp = _itemArrayNew( 5 ); - - itemSqlname = _itemPutC( NULL, sqlda->sqlvar[i].sqlname ); - _itemArrayPut( aTemp, 1, itemSqlname ); - - itemSqltype = _itemPutNL( NULL, (long)dtype ); - _itemArrayPut( aTemp, 2, itemSqltype ); - - itemSqllen = _itemPutNL( NULL, sqlda->sqlvar[i].sqllen ); - _itemArrayPut( aTemp, 3, itemSqllen ); - - itemSqlscale = _itemPutNL( NULL, sqlda->sqlvar[i].sqlscale ); - _itemArrayPut( aTemp, 4, itemSqlscale ); - - itemRelname = _itemPutC( NULL, sqlda->sqlvar[i].relname ); - _itemArrayPut( aTemp, 5, itemRelname ); - - _itemRelease( itemSqlname ); - _itemRelease( itemSqltype ); - _itemRelease( itemSqllen ); - _itemRelease( itemSqlscale ); - _itemRelease( itemRelname ); - - _itemArrayPut( aNew, i+1, aTemp ); - _itemRelease( aTemp ); - } - - if ( !sqlda->sqld ) { - // Execute and commit non-select querys - if ( isc_dsql_execute ( status, &trans, &stmt, dialect, NULL ) ) - ERREXIT(status); - - } else { - if ( isc_dsql_execute ( status, &trans, &stmt, dialect, sqlda ) ) - ERREXIT(status); - } - - qry_handle = _itemArrayNew(6); - - temp = hb_itemPutPtr( NULL, ( void * ) stmt ); - hb_arraySet(qry_handle, 1, temp); - _itemRelease(temp); - - temp = hb_itemPutPtr( NULL, ( void * ) sqlda ); - hb_arraySet(qry_handle, 2, temp); - _itemRelease(temp); - - if (! hb_parinfo(4)) - { - temp = hb_itemPutPtr( NULL, ( void * ) trans ); - hb_arraySet(qry_handle, 3, temp); - _itemRelease(temp); - } - - temp = _itemPutNL(NULL, (long) num_cols); - hb_arraySet(qry_handle, 4, temp); - _itemRelease(temp); - - temp = _itemPutNL(NULL, (long) dialect); - hb_arraySet(qry_handle, 5, temp); - _itemRelease(temp); - - hb_arraySet(qry_handle, 6, aNew); - - _itemReturn(qry_handle); - _itemRelease(qry_handle); - _itemRelease(aNew); -} - - -HB_FUNC(FBFETCH) -{ - isc_stmt_handle stmt = NULL; - ISC_STATUS status[MAX_FIELDS]; - XSQLDA ISC_FAR * sqlda; - long fetch_stat; - int dialect; - - PHB_ITEM aParam ; - - if (ISARRAY( 1 ) ) - { - aParam = hb_param(1,HB_IT_ARRAY); - - stmt = ( isc_stmt_handle ) hb_itemGetPtr(hb_itemArrayGet( aParam, 1 )); - sqlda = ( XSQLDA ISC_FAR * ) hb_itemGetPtr(hb_itemArrayGet( aParam, 2 )); - dialect = hb_itemGetNI(hb_itemArrayGet( aParam, 5 )); - - fetch_stat = isc_dsql_fetch(status, &stmt, dialect, sqlda); - - if (fetch_stat != 100L) - ERREXIT(status); - - } - _retnl(fetch_stat); -} - - -HB_FUNC(FBFREE) -{ - isc_stmt_handle stmt = NULL; - isc_tr_handle trans = NULL; - ISC_STATUS status[MAX_FIELDS]; - XSQLDA ISC_FAR * sqlda; - - PHB_ITEM aParam ; - - if (ISARRAY( 1 ) ) - { - aParam = hb_param(1,HB_IT_ARRAY); - - stmt = ( isc_stmt_handle ) hb_itemGetPtr(hb_itemArrayGet( aParam, 1 )); - sqlda = ( XSQLDA ISC_FAR * ) hb_itemGetPtr(hb_itemArrayGet( aParam, 2 )); - trans = ( isc_tr_handle ) hb_itemGetPtr( hb_itemArrayGet( aParam, 3 )); - - if (isc_dsql_free_statement(status, &stmt, DSQL_drop)) - ERREXIT(status); - - if (trans) - if (isc_commit_transaction(status, &trans)) - ERREXIT(status); - - if ( sqlda ) - hb_xfree( sqlda ); - - _retnl(1); - } - else - _retnl(0); - -} - - -HB_FUNC(FBGETDATA) -{ - int pos; - short dtype; - char data[MAX_BUFFER], *p; - char date_s[25]; - - struct tm times; - XSQLVAR *var; - XSQLDA ISC_FAR * sqlda; - ISC_STATUS status[MAX_FIELDS]; - ISC_QUAD *blob_id; - - PHB_ITEM aParam ; - PHB_ITEM temp; - - aParam = hb_param(1,HB_IT_ARRAY); - - sqlda = ( XSQLDA ISC_FAR * ) hb_itemGetPtr(hb_itemArrayGet( aParam, 2 )); - pos = (int) hb_parnl(2); - - pos--; - - if ( ( pos + 1 ) > sqlda->sqln ) - ERREXIT(status); - - var = sqlda->sqlvar; - - var += pos; - - dtype = var->sqltype & ~1; - p = data; - - if ( ( var->sqltype & 1 ) && ( *var->sqlind < 0 ) ) { - /* null field */ - _ret(); - - } else { - switch ( dtype ) { - case SQL_TEXT: - case SQL_VARYING: - _retclen( var->sqldata, var->sqllen ); - break; - - case SQL_TIMESTAMP: - isc_decode_timestamp ( ( ISC_TIMESTAMP ISC_FAR * ) var->sqldata, × ); - sprintf ( date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04lu", - times.tm_year + 1900, - times.tm_mon + 1, - times.tm_mday, - times.tm_hour, - times.tm_min, - times.tm_sec, - ( ( ISC_TIMESTAMP * ) var->sqldata )->timestamp_time % 10000 ); - sprintf ( p, "%*s ", 24, date_s ); - - _retc(p); - break; - - case SQL_TYPE_DATE: - isc_decode_sql_date ( ( ISC_DATE ISC_FAR * ) var->sqldata, × ); - sprintf ( date_s, "%04d-%02d-%02d", times.tm_year + 1900, times.tm_mon + 1, times.tm_mday ); - sprintf ( p, "%*s ", 8, date_s ); - - _retc(p); - break; - - case SQL_TYPE_TIME: - isc_decode_sql_time ( ( ISC_TIME ISC_FAR * ) var->sqldata, × ); - sprintf ( date_s, "%02d:%02d:%02d.%04lu", - times.tm_hour, - times.tm_min, - times.tm_sec, ( *( ( ISC_TIME * ) var->sqldata ) ) % 10000 ); - sprintf ( p, "%*s ", 13, date_s ); - - _retc(p); - break; - - case SQL_BLOB: - - blob_id = ( ISC_QUAD * ) var->sqldata; - - temp = hb_itemPutPtr( NULL, ( void * ) blob_id ); - _itemReturn(temp); - _itemRelease(temp); - - break; - - case SQL_SHORT: - case SQL_LONG: - case SQL_INT64: - { - ISC_INT64 value; - short field_width; - short dscale; - switch (dtype) - { - case SQL_SHORT: - value = (ISC_INT64) *(short ISC_FAR *) var->sqldata; - field_width = 6; - break; - - case SQL_LONG: - value = (ISC_INT64) *(long ISC_FAR *) var->sqldata; - field_width = 11; - break; - - case SQL_INT64: - value = (ISC_INT64) *(ISC_INT64 ISC_FAR *) var->sqldata; - field_width = 21; - break; - } - - dscale = var->sqlscale; - - if (dscale < 0) - { - ISC_INT64 tens; - short i; - - tens = 1; - for (i = 0; i > dscale; i--) - tens *= 10; - - if (value >= 0) - sprintf (p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d", - field_width - 1 + dscale, - (ISC_INT64) value / tens, - -dscale, - (ISC_INT64) value % tens); - - else if ((value / tens) != 0) - sprintf (p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d", - field_width - 1 + dscale, - (ISC_INT64) (value / tens), - -dscale, - (ISC_INT64) -(value % tens)); - - else - sprintf (p, "%*s.%0*" ISC_INT64_FORMAT "d", - field_width - 1 + dscale, - "-0", - -dscale, - (ISC_INT64) -(value % tens)); - } - else if (dscale) - sprintf (p, "%*" ISC_INT64_FORMAT "d%0*d", field_width, (ISC_INT64) value, dscale, 0); - else - sprintf (p, "%*" ISC_INT64_FORMAT "d", field_width, (ISC_INT64) value); - }; - _retc(p); - break; - - case SQL_FLOAT: - sprintf(p, "%15g ", *(float ISC_FAR *) (var->sqldata)); - _retc(p); - break; - - case SQL_DOUBLE: - sprintf(p, "%24f ", *(double ISC_FAR *) (var->sqldata)); - _retc(p); - break; - - default: - _ret(); - break; - } - } -} - - -HB_FUNC(FBGETBLOB) -{ - ISC_STATUS status[MAX_FIELDS]; - isc_db_handle db = NULL; - isc_tr_handle trans = NULL; - isc_blob_handle blob_handle = NULL; - short blob_seg_len; - char *blob_segment; - ISC_QUAD *blob_id; - char p[MAX_BUFFER]; - long blob_stat; - - ITEM temp; - ITEM aNew; - - db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); - blob_id = ( ISC_QUAD * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); - - if (_parinfo(3)) { - trans = (isc_tr_handle) hb_itemGetPtr( hb_param( 3, HB_IT_POINTER ) ); - } else { - if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) { - ERREXIT(status); - } - } - - if (isc_open_blob2(status, &db, &trans, &blob_handle, blob_id, 0, NULL)) - ERREXIT(status); - - // Get blob segments and their lengths and print each segment. - blob_stat = isc_get_segment(status, &blob_handle, - (unsigned short ISC_FAR *) &blob_seg_len, - sizeof(blob_segment), blob_segment); - - if (blob_stat == 0 || status[1] == isc_segment) - aNew = _itemArrayNew( 0 ); - - while (blob_stat == 0 || status[1] == isc_segment) - { - //p = ( char * ) hb_xgrab( blob_seg_len + 1 ); - sprintf( p, "%*.*s", blob_seg_len, blob_seg_len, blob_segment); - - temp = _itemPutC( NULL, p ); - hb_arrayAdd( aNew, temp ) ; - _itemRelease(temp); - - //hb_xfree(p); - blob_stat = isc_get_segment(status, &blob_handle, - (unsigned short ISC_FAR *)&blob_seg_len, - sizeof(blob_segment), blob_segment); - } - - if (isc_close_blob(status, &blob_handle)) { - _itemRelease(aNew); - ERREXIT(status); - } - - if (!_parinfo(3)) - if ( isc_commit_transaction ( status, &trans ) ) - ERREXIT(status); - - _itemReturn(aNew); - _itemRelease(aNew); -} +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * Firebird RDBMS low level (client api) interface code. + * + * Copyright 2003 Rodrigo Moreno rodrigo_moreno@yahoo.com + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + * See doc/license.txt for licensing terms. + * + */ + +#define _CLIPDEFS_H +#if defined(HB_OS_WIN_32_USED) + #include +#endif + +#include +#include +#include +#include + +#include "extend.api" +#include "item.api" +#include "hbapiitm.h" +#include "ibase.h" + +#define DIALECT 1 +#define MAX_FIELDS 5 +#define MAX_LEN 256 +#define MAX_BUFFER 1024 + +#define ERREXIT(status) { _retnl(isc_sqlcode(status)); return; } + +#ifndef ISC_INT64_FORMAT + +#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__BORLANDC__) && defined(__WIN32__)) +#define ISC_INT64_FORMAT "I64" +#else +#define ISC_INT64_FORMAT "ll" +#endif +#endif + +HB_FUNC(FBCREATEDB) +{ + isc_db_handle newdb = NULL; + isc_tr_handle trans = NULL; + long status[20]; + char create_db[MAX_BUFFER]; + + char *db_name; + char *user; + char *pass; + char *charset; + int page; + int dialect; + + if (hb_pcount() != 6) + { + _retni(0); + return; + } + + db_name = hb_parcx(1); + user = hb_parcx(2); + pass = hb_parcx(3); + page = hb_parni(4); + charset = hb_parcx(5); + dialect = hb_parni(6); + + sprintf(create_db, + "CREATE DATABASE '%s' USER '%s' PASSWORD '%s' PAGE_SIZE = %i DEFAULT CHARACTER SET %s", + db_name, user, pass, page, charset ); + + if (isc_dsql_execute_immediate(status, &newdb, &trans, 0, create_db, dialect, NULL)) + ERREXIT(status); + + _retni(1); +} + + +HB_FUNC(FBCONNECT) +{ + ISC_STATUS status[MAX_FIELDS]; + isc_db_handle db = NULL; + char *db_connect = NULL; + char *user = NULL; + char *passwd = NULL; + char dpb[128]; + int i = 0, len; + + PHB_ITEM db_handle; + + if (hb_parinfo(1)) + db_connect = hb_parcx(1); + + if (hb_parinfo(2)) + user = hb_parcx(2); + + if (hb_parinfo(3)) + passwd = hb_parcx(3); + + dpb[i++] = isc_dpb_version1; + + dpb[i++] = isc_dpb_user_name; + len = strlen(user); + dpb[i++] = (char) len; + strncpy(&(dpb[i]), user, len); + i += len; + + dpb[i++] = isc_dpb_password; + len = strlen (passwd); + dpb[i++] = len; + strncpy(&(dpb[i]), passwd, len); + i += len; + + if ( isc_attach_database ( status, 0, db_connect, &db, i, dpb ) ) + ERREXIT(status); + + db_handle = hb_itemPutPtr( NULL, ( void * ) db ); + _itemReturn(db_handle); + _itemRelease(db_handle); +} + + +HB_FUNC(FBCLOSE) +{ + isc_db_handle db = NULL; + long status[20]; + + db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + + if ( isc_detach_database ( status, &db ) ) + ERREXIT(status); + + _retnl(1); +} + + +HB_FUNC(FBERROR) +{ + int sqlcode; + char msg[MAX_BUFFER]; + + sqlcode = hb_parni(1); + + isc_sql_interprete(sqlcode, msg, 512); + + _retc(msg); +} + +HB_FUNC(FBSTARTTRANSACTION) +{ + isc_db_handle db = NULL; + isc_tr_handle trans = NULL; + long status[MAX_FIELDS]; + + PHB_ITEM var; + + db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + + if (isc_start_transaction(status, &trans, 1, &db, 0, NULL)) + ERREXIT(status); + + var = hb_itemPutPtr( NULL, ( void * ) trans ); + _itemReturn(var); + _itemRelease(var); +} + + +HB_FUNC(FBCOMMIT) +{ + isc_tr_handle trans = NULL; + long status[MAX_FIELDS]; + + trans = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + + if (isc_commit_transaction(status, &trans)) + ERREXIT(status); + + trans = NULL; + _retnl(1); +} + +HB_FUNC(FBROLLBACK) +{ + isc_tr_handle trans = NULL; + long status[MAX_FIELDS]; + + trans = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + + if (isc_rollback_transaction(status, &trans)) + ERREXIT(status); + + trans = NULL; + _retnl(1); +} + + +HB_FUNC(FBEXECUTE) +{ + isc_db_handle db = NULL; + isc_tr_handle trans = NULL; + char *exec_str; + long status[20]; + long status_rollback[20]; + int dialect; + + db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + exec_str = hb_parcx(2); + dialect = hb_parni(3); + + if (hb_parinfo(4)) { + trans = (isc_tr_handle) hb_itemGetPtr( hb_param( 4, HB_IT_POINTER ) ); + } else { + if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) + ERREXIT(status); + } + + if (isc_dsql_execute_immediate(status, &db, &trans, 0, exec_str, dialect, NULL)) { + if (! hb_parinfo(4)) + isc_rollback_transaction ( status_rollback, &trans ); + + ERREXIT(status); + } + + if (!hb_parinfo(4)) + if ( isc_commit_transaction ( status, &trans ) ) + ERREXIT(status); + + _retnl(1); +} + +HB_FUNC(FBQUERY) +{ + isc_db_handle db = NULL; + isc_tr_handle trans = NULL; + ISC_STATUS status[MAX_FIELDS]; + XSQLDA ISC_FAR * sqlda; + isc_stmt_handle stmt = NULL; + XSQLVAR *var; + + char sel_str[MAX_LEN]; + int dialect; + int n, i, dtype; + int num_cols; + + ITEM qry_handle; + ITEM temp; + ITEM aTemp; + ITEM aNew; + + ITEM itemSqlname; + ITEM itemSqltype; + ITEM itemSqllen ; + ITEM itemSqlscale; + ITEM itemRelname; + + db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + strcpy(sel_str, hb_parcx(2)); + + if (hb_parinfo(3)) { + dialect = hb_parni(3); + } else { + dialect = DIALECT; + } + + if (hb_parinfo(4)) { + trans = (isc_tr_handle) hb_itemGetPtr( hb_param( 4, HB_IT_POINTER ) ); + + } else if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) + ERREXIT(status); + + // Allocate an output SQLDA. Just to check number of columns + sqlda = ( XSQLDA * ) hb_xgrab( XSQLDA_LENGTH ( 1 ) ); + sqlda->sqln = 1; + sqlda->version = 1; + + // Allocate a statement + if (isc_dsql_allocate_statement(status, &db, &stmt)) + ERREXIT(status); + + // Prepare the statement. + if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, dialect, sqlda)) + ERREXIT(status); + + // Describe sql contents + if (isc_dsql_describe(status, &stmt, dialect, sqlda)) + ERREXIT(status); + + num_cols = sqlda->sqld; + aNew = _itemArrayNew( num_cols ); + + // Relocate necessary number of columns + if ( sqlda->sqld > sqlda->sqln ) { + hb_xfree( sqlda ); + n = sqlda->sqld; + sqlda = ( XSQLDA * ) hb_xgrab( XSQLDA_LENGTH ( n ) ); + sqlda->sqln = n; + sqlda->version = 1; + + if (isc_dsql_describe(status, &stmt, dialect, sqlda)) + ERREXIT(status); + } + + for ( i = 0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++ ) { + dtype = ( var->sqltype & ~1 ); + switch ( dtype ) { + case SQL_VARYING: + var->sqltype = SQL_TEXT; + var->sqldata = ( char * ) hb_xgrab( sizeof ( char ) * var->sqllen + 2 ); + break; + case SQL_TEXT: + var->sqldata = ( char * ) hb_xgrab( sizeof ( char ) * var->sqllen + 2 ); + break; + case SQL_LONG: + var->sqltype = SQL_LONG; + var->sqldata = ( char * ) hb_xgrab( sizeof ( long ) ); + break; + default: + var->sqldata = ( char * ) hb_xgrab( sizeof ( char ) * var->sqllen ); + break; + } + if ( var->sqltype & 1 ) { + var->sqlind = ( short * ) hb_xgrab( sizeof ( short ) ); + } + + aTemp = _itemArrayNew( 5 ); + + itemSqlname = _itemPutC( NULL, sqlda->sqlvar[i].sqlname ); + _itemArrayPut( aTemp, 1, itemSqlname ); + + itemSqltype = _itemPutNL( NULL, (long)dtype ); + _itemArrayPut( aTemp, 2, itemSqltype ); + + itemSqllen = _itemPutNL( NULL, sqlda->sqlvar[i].sqllen ); + _itemArrayPut( aTemp, 3, itemSqllen ); + + itemSqlscale = _itemPutNL( NULL, sqlda->sqlvar[i].sqlscale ); + _itemArrayPut( aTemp, 4, itemSqlscale ); + + itemRelname = _itemPutC( NULL, sqlda->sqlvar[i].relname ); + _itemArrayPut( aTemp, 5, itemRelname ); + + _itemRelease( itemSqlname ); + _itemRelease( itemSqltype ); + _itemRelease( itemSqllen ); + _itemRelease( itemSqlscale ); + _itemRelease( itemRelname ); + + _itemArrayPut( aNew, i+1, aTemp ); + _itemRelease( aTemp ); + } + + if ( !sqlda->sqld ) { + // Execute and commit non-select querys + if ( isc_dsql_execute ( status, &trans, &stmt, dialect, NULL ) ) + ERREXIT(status); + + } else { + if ( isc_dsql_execute ( status, &trans, &stmt, dialect, sqlda ) ) + ERREXIT(status); + } + + qry_handle = _itemArrayNew(6); + + temp = hb_itemPutPtr( NULL, ( void * ) stmt ); + hb_arraySet(qry_handle, 1, temp); + _itemRelease(temp); + + temp = hb_itemPutPtr( NULL, ( void * ) sqlda ); + hb_arraySet(qry_handle, 2, temp); + _itemRelease(temp); + + if (! hb_parinfo(4)) + { + temp = hb_itemPutPtr( NULL, ( void * ) trans ); + hb_arraySet(qry_handle, 3, temp); + _itemRelease(temp); + } + + temp = _itemPutNL(NULL, (long) num_cols); + hb_arraySet(qry_handle, 4, temp); + _itemRelease(temp); + + temp = _itemPutNL(NULL, (long) dialect); + hb_arraySet(qry_handle, 5, temp); + _itemRelease(temp); + + hb_arraySet(qry_handle, 6, aNew); + + _itemReturn(qry_handle); + _itemRelease(qry_handle); + _itemRelease(aNew); +} + + +HB_FUNC(FBFETCH) +{ + isc_stmt_handle stmt = NULL; + ISC_STATUS status[MAX_FIELDS]; + XSQLDA ISC_FAR * sqlda; + long fetch_stat; + int dialect; + + PHB_ITEM aParam ; + + if (ISARRAY( 1 ) ) + { + aParam = hb_param(1,HB_IT_ARRAY); + + stmt = ( isc_stmt_handle ) hb_itemGetPtr(hb_itemArrayGet( aParam, 1 )); + sqlda = ( XSQLDA ISC_FAR * ) hb_itemGetPtr(hb_itemArrayGet( aParam, 2 )); + dialect = hb_itemGetNI(hb_itemArrayGet( aParam, 5 )); + + fetch_stat = isc_dsql_fetch(status, &stmt, dialect, sqlda); + + if (fetch_stat != 100L) + ERREXIT(status); + + } + _retnl(fetch_stat); +} + + +HB_FUNC(FBFREE) +{ + isc_stmt_handle stmt = NULL; + isc_tr_handle trans = NULL; + ISC_STATUS status[MAX_FIELDS]; + XSQLDA ISC_FAR * sqlda; + + PHB_ITEM aParam ; + + if (ISARRAY( 1 ) ) + { + aParam = hb_param(1,HB_IT_ARRAY); + + stmt = ( isc_stmt_handle ) hb_itemGetPtr(hb_itemArrayGet( aParam, 1 )); + sqlda = ( XSQLDA ISC_FAR * ) hb_itemGetPtr(hb_itemArrayGet( aParam, 2 )); + trans = ( isc_tr_handle ) hb_itemGetPtr( hb_itemArrayGet( aParam, 3 )); + + if (isc_dsql_free_statement(status, &stmt, DSQL_drop)) + ERREXIT(status); + + if (trans) + if (isc_commit_transaction(status, &trans)) + ERREXIT(status); + + if ( sqlda ) + hb_xfree( sqlda ); + + _retnl(1); + } + else + _retnl(0); + +} + + +HB_FUNC(FBGETDATA) +{ + int pos; + short dtype; + char data[MAX_BUFFER], *p; + char date_s[25]; + + struct tm times; + XSQLVAR *var; + XSQLDA ISC_FAR * sqlda; + ISC_STATUS status[MAX_FIELDS]; + ISC_QUAD *blob_id; + + PHB_ITEM aParam ; + PHB_ITEM temp; + + aParam = hb_param(1,HB_IT_ARRAY); + + sqlda = ( XSQLDA ISC_FAR * ) hb_itemGetPtr(hb_itemArrayGet( aParam, 2 )); + pos = (int) hb_parnl(2); + + pos--; + + if ( ( pos + 1 ) > sqlda->sqln ) + ERREXIT(status); + + var = sqlda->sqlvar; + + var += pos; + + dtype = var->sqltype & ~1; + p = data; + + if ( ( var->sqltype & 1 ) && ( *var->sqlind < 0 ) ) { + /* null field */ + _ret(); + + } else { + switch ( dtype ) { + case SQL_TEXT: + case SQL_VARYING: + _retclen( var->sqldata, var->sqllen ); + break; + + case SQL_TIMESTAMP: + isc_decode_timestamp ( ( ISC_TIMESTAMP ISC_FAR * ) var->sqldata, × ); + sprintf ( date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04lu", + times.tm_year + 1900, + times.tm_mon + 1, + times.tm_mday, + times.tm_hour, + times.tm_min, + times.tm_sec, + ( ( ISC_TIMESTAMP * ) var->sqldata )->timestamp_time % 10000 ); + sprintf ( p, "%*s ", 24, date_s ); + + _retc(p); + break; + + case SQL_TYPE_DATE: + isc_decode_sql_date ( ( ISC_DATE ISC_FAR * ) var->sqldata, × ); + sprintf ( date_s, "%04d-%02d-%02d", times.tm_year + 1900, times.tm_mon + 1, times.tm_mday ); + sprintf ( p, "%*s ", 8, date_s ); + + _retc(p); + break; + + case SQL_TYPE_TIME: + isc_decode_sql_time ( ( ISC_TIME ISC_FAR * ) var->sqldata, × ); + sprintf ( date_s, "%02d:%02d:%02d.%04lu", + times.tm_hour, + times.tm_min, + times.tm_sec, ( *( ( ISC_TIME * ) var->sqldata ) ) % 10000 ); + sprintf ( p, "%*s ", 13, date_s ); + + _retc(p); + break; + + case SQL_BLOB: + + blob_id = ( ISC_QUAD * ) var->sqldata; + + temp = hb_itemPutPtr( NULL, ( void * ) blob_id ); + _itemReturn(temp); + _itemRelease(temp); + + break; + + case SQL_SHORT: + case SQL_LONG: + case SQL_INT64: + { + ISC_INT64 value; + short field_width; + short dscale; + switch (dtype) + { + case SQL_SHORT: + value = (ISC_INT64) *(short ISC_FAR *) var->sqldata; + field_width = 6; + break; + + case SQL_LONG: + value = (ISC_INT64) *(long ISC_FAR *) var->sqldata; + field_width = 11; + break; + + case SQL_INT64: + value = (ISC_INT64) *(ISC_INT64 ISC_FAR *) var->sqldata; + field_width = 21; + break; + } + + dscale = var->sqlscale; + + if (dscale < 0) + { + ISC_INT64 tens; + short i; + + tens = 1; + for (i = 0; i > dscale; i--) + tens *= 10; + + if (value >= 0) + sprintf (p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d", + field_width - 1 + dscale, + (ISC_INT64) value / tens, + -dscale, + (ISC_INT64) value % tens); + + else if ((value / tens) != 0) + sprintf (p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d", + field_width - 1 + dscale, + (ISC_INT64) (value / tens), + -dscale, + (ISC_INT64) -(value % tens)); + + else + sprintf (p, "%*s.%0*" ISC_INT64_FORMAT "d", + field_width - 1 + dscale, + "-0", + -dscale, + (ISC_INT64) -(value % tens)); + } + else if (dscale) + sprintf (p, "%*" ISC_INT64_FORMAT "d%0*d", field_width, (ISC_INT64) value, dscale, 0); + else + sprintf (p, "%*" ISC_INT64_FORMAT "d", field_width, (ISC_INT64) value); + }; + _retc(p); + break; + + case SQL_FLOAT: + sprintf(p, "%15g ", *(float ISC_FAR *) (var->sqldata)); + _retc(p); + break; + + case SQL_DOUBLE: + sprintf(p, "%24f ", *(double ISC_FAR *) (var->sqldata)); + _retc(p); + break; + + default: + _ret(); + break; + } + } +} + + +HB_FUNC(FBGETBLOB) +{ + ISC_STATUS status[MAX_FIELDS]; + isc_db_handle db = NULL; + isc_tr_handle trans = NULL; + isc_blob_handle blob_handle = NULL; + short blob_seg_len; + char *blob_segment; + ISC_QUAD *blob_id; + char p[MAX_BUFFER]; + long blob_stat; + + ITEM temp; + ITEM aNew; + + db = ( isc_db_handle ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) ); + blob_id = ( ISC_QUAD * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) ); + + if (_parinfo(3)) { + trans = (isc_tr_handle) hb_itemGetPtr( hb_param( 3, HB_IT_POINTER ) ); + } else { + if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) { + ERREXIT(status); + } + } + + if (isc_open_blob2(status, &db, &trans, &blob_handle, blob_id, 0, NULL)) + ERREXIT(status); + + // Get blob segments and their lengths and print each segment. + blob_stat = isc_get_segment(status, &blob_handle, + (unsigned short ISC_FAR *) &blob_seg_len, + sizeof(blob_segment), blob_segment); + + if (blob_stat == 0 || status[1] == isc_segment) + aNew = _itemArrayNew( 0 ); + + while (blob_stat == 0 || status[1] == isc_segment) + { + //p = ( char * ) hb_xgrab( blob_seg_len + 1 ); + sprintf( p, "%*.*s", blob_seg_len, blob_seg_len, blob_segment); + + temp = _itemPutC( NULL, p ); + hb_arrayAdd( aNew, temp ) ; + _itemRelease(temp); + + //hb_xfree(p); + blob_stat = isc_get_segment(status, &blob_handle, + (unsigned short ISC_FAR *)&blob_seg_len, + sizeof(blob_segment), blob_segment); + } + + if (isc_close_blob(status, &blob_handle)) { + _itemRelease(aNew); + ERREXIT(status); + } + + if (!_parinfo(3)) + if ( isc_commit_transaction ( status, &trans ) ) + ERREXIT(status); + + _itemReturn(aNew); + _itemRelease(aNew); +} diff --git a/harbour/contrib/firebird/make_b32.bat b/harbour/contrib/firebird/make_b32.bat index 06fe3c275f..f4fb593135 100644 --- a/harbour/contrib/firebird/make_b32.bat +++ b/harbour/contrib/firebird/make_b32.bat @@ -1,6 +1,6 @@ @echo off rem -rem $Id: make_b32.bat 7974 2007-11-14 23:24:27Z vszakats $ +rem $Id$ rem rem --------------------------------------------------------------- diff --git a/harbour/contrib/firebird/make_vc.bat b/harbour/contrib/firebird/make_vc.bat index fc284ef86e..be50e6fcfe 100644 --- a/harbour/contrib/firebird/make_vc.bat +++ b/harbour/contrib/firebird/make_vc.bat @@ -1,6 +1,6 @@ @echo off rem -rem $Id: make_vc.bat 7974 2007-11-14 23:24:27Z vszakats $ +rem $Id$ rem rem --------------------------------------------------------------- diff --git a/harbour/contrib/firebird/readme.txt b/harbour/contrib/firebird/readme.txt index 2d51f01eae..3bf1dbbeab 100644 --- a/harbour/contrib/firebird/readme.txt +++ b/harbour/contrib/firebird/readme.txt @@ -1,55 +1,55 @@ - -README 23/12/2003 - Harbour Low Level api for Firebird and Interbase RDBMS - -This work is not finished yet. It's to be seem like Harbour TMysql routines. - -To use with bcc, you need import library, ex: implib fbclient.lib fbclient.dll or implib gds32.lib gds32.dll. -On Linux you will need link fbclient.so, this can be found usually at /usr/lib. - -For full firebird documentation look at: - -Firebird home: http://firebird.sourceforge.net/index.php -Api: http://www.ibphoenix.com/downloads/60ApiGuide.zip -Data Definition: http://www.ibphoenix.com/downloads/60DataDef.zip -Language Reference: http://www.ibphoenix.com/downloads/60LangRef.zip -Developers guide: http://www.ibphoenix.com/downloads/60DevGuide.zip - -The Class implementation has no all implementation like TMysql has, because Firebird it's diferent. -For example, you can't navigate in records like Mysql do, ex: Getrow( number of row ), in firebird you can -just go forward. - -You will need ibase.h, it can be found at firebird/include - -FILES: - -firebird.c - Low level api -TFirebird.prg - Class implementation, it's to be seems like TMysql. - -tests\simple.prg - Simple test class -tests\stress.prg - Stress test class -tests\test.prg - Testing using only low level api -tests\test.c - Pure C code to test firebird access. - -TODO: - -Full implementation of blob control. For now, we have only partial control, only for text blobs (sybtype 1). -Improve Insert and Update commands using DSQL. - -Implements to do: -FBOpenBlob( blob_id ) -FBReadBlob(blob_id, string, segment_size) - -FBCreateBlob() -FBPutBlob(blob_id, string, segment_size) - -FBCloseBlob( blob_id ) - - -BUGS: - -Fix a few windows gpf and linux segment fault. I Need some help to find what's going on here. - - -That's all folks and sorry my poor english - + +README 23/12/2003 - Harbour Low Level api for Firebird and Interbase RDBMS + +This work is not finished yet. It's to be seem like Harbour TMysql routines. + +To use with bcc, you need import library, ex: implib fbclient.lib fbclient.dll or implib gds32.lib gds32.dll. +On Linux you will need link fbclient.so, this can be found usually at /usr/lib. + +For full firebird documentation look at: + +Firebird home: http://firebird.sourceforge.net/index.php +Api: http://www.ibphoenix.com/downloads/60ApiGuide.zip +Data Definition: http://www.ibphoenix.com/downloads/60DataDef.zip +Language Reference: http://www.ibphoenix.com/downloads/60LangRef.zip +Developers guide: http://www.ibphoenix.com/downloads/60DevGuide.zip + +The Class implementation has no all implementation like TMysql has, because Firebird it's diferent. +For example, you can't navigate in records like Mysql do, ex: Getrow( number of row ), in firebird you can +just go forward. + +You will need ibase.h, it can be found at firebird/include + +FILES: + +firebird.c - Low level api +TFirebird.prg - Class implementation, it's to be seems like TMysql. + +tests\simple.prg - Simple test class +tests\stress.prg - Stress test class +tests\test.prg - Testing using only low level api +tests\test.c - Pure C code to test firebird access. + +TODO: + +Full implementation of blob control. For now, we have only partial control, only for text blobs (sybtype 1). +Improve Insert and Update commands using DSQL. + +Implements to do: +FBOpenBlob( blob_id ) +FBReadBlob(blob_id, string, segment_size) + +FBCreateBlob() +FBPutBlob(blob_id, string, segment_size) + +FBCloseBlob( blob_id ) + + +BUGS: + +Fix a few windows gpf and linux segment fault. I Need some help to find what's going on here. + + +That's all folks and sorry my poor english + Rodrigo Moreno - rodrigo_moreno@yahoo.com \ No newline at end of file diff --git a/harbour/contrib/firebird/test/Makefile b/harbour/contrib/firebird/test/Makefile index a480da9c1c..5db94ce5cb 100644 --- a/harbour/contrib/firebird/test/Makefile +++ b/harbour/contrib/firebird/test/Makefile @@ -1,32 +1,32 @@ -# -# $Id: Makefile,v 1.1 2003/12/31 00:24:35 lculik Exp $ -# - -ifeq ($(HB_MAIN),) - HB_MAIN = std -endif - -ROOT = ../../../ - -CONTRIBS=\ - firebird \ - -PRG_SOURCES=\ - simple.prg \ - -PRG_MAIN=\ - simple.prg - -LIBS=\ - debug \ - vm \ - rtl \ - lang \ - rdd \ - rtl \ - vm \ - macro \ - common \ - fbclient \ - -include $(TOP)$(ROOT)config/bin.cf +# +# $Id$ +# + +ifeq ($(HB_MAIN),) + HB_MAIN = std +endif + +ROOT = ../../../ + +CONTRIBS=\ + firebird \ + +PRG_SOURCES=\ + simple.prg \ + +PRG_MAIN=\ + simple.prg + +LIBS=\ + debug \ + vm \ + rtl \ + lang \ + rdd \ + rtl \ + vm \ + macro \ + common \ + fbclient \ + +include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/contrib/firebird/test/bld_b32.bat b/harbour/contrib/firebird/test/bld_b32.bat index 4375049cb3..bcf79eccc4 100644 --- a/harbour/contrib/firebird/test/bld_b32.bat +++ b/harbour/contrib/firebird/test/bld_b32.bat @@ -1,6 +1,6 @@ @echo off rem -rem $Id: bld_b32.bat 7941 2007-11-11 01:42:42Z vszakats $ +rem $Id$ rem if A%1 == A GOTO :SYNTAX diff --git a/harbour/contrib/firebird/test/simple.prg b/harbour/contrib/firebird/test/simple.prg index 1fb60426ee..a208cce1b4 100644 --- a/harbour/contrib/firebird/test/simple.prg +++ b/harbour/contrib/firebird/test/simple.prg @@ -1,188 +1,188 @@ -/* - * $Id: atrepl.c 7583 2007-07-06 21:17:36Z druzus $ - */ - -#include "common.ch" - -Function main() - Local oServer, oQuery, oRow, i, x, aTables, aStruct, aKey - - Local cServer := '192.168.1.33:D:\firebird\test\test.gdb' - Local cUser := 'sysdba' - Local cPass := 'masterkey' - Local nDialect := 1 - Local cQuery - - if File('test.gdb') - FErase('test.gdb') - end - - ? FBCreateDB('test.gdb', cuser, cpass, 1024, 'ASCII', nDialect ) - - ? "Connecting..." - - oServer := TFBServer():New(cServer, cUser, cPass, nDialect) - - if oServer:NetErr() - ? oServer:Error() - quit - end - - ? 'Tables...' - - For x := 1 to 1 - aTables := oServer:ListTables() - - For i := 1 to Len(aTables) - ? aTables[i] - next - Next - - ? 'Using implicit transaction...' - - if oServer:TableExists('TEST') - oServer:Execute('DROP TABLE Test') - oServer:Execute('DROP DOMAIN boolean_field') - end - - ? 'Creating domain for boolean fields...' - oServer:Execute('create domain boolean_field as smallint default 0 not null check (value in (0,1))') - - oServer:StartTransaction() - ? 'Creating test table...' - cQuery := 'CREATE TABLE test(' - cQuery += ' Code SmallInt not null primary key, ' - cQuery += ' dept Integer, ' - cQuery += ' Name Varchar(40), ' - cQuery += ' Sales boolean_field, ' - cQuery += ' Tax Float, ' - cQuery += ' Salary Double Precision, ' - cQuery += ' Budget Numeric(12,2), ' - cQuery += ' Discount Decimal(5,2), ' - cQuery += ' Creation Date, ' - cQuery += ' Description blob sub_type 1 segment size 40 ) ' - - oServer:Execute(cQuery) - - if oServer:neterr() - ? oServer:Error() - end - - oServer:Commit() - - oQuery := oServer:Query('SELECT code, dept, name, sales, salary, creation FROM test') - wait - - - ? 'Structure of test table' - aStruct := oServer:TableStruct('test') - - For i := 1 to Len(aStruct) - ? - For x := 1 to Len(aStruct[i]) - ?? aStruct[i,x] - Next - next - - ? 'Inserting, declared transaction control ' - oServer:StartTransaction() - - For i := 1 to 100 - cQuery := 'INSERT INTO test(code, dept, name, sales, tax, salary, budget, Discount, Creation, Description) ' - cQuery += 'VALUES( ' + str(i) + ', 2, "TEST", 1, 5, 3000, 1500.2, 7.5, "12-22-2003", "Short Description about what ? ")' - - oServer:Execute(cQuery) - - if oServer:neterr() - ? oServer:error() - end - Next - - oServer:Commit() - - oQuery := oServer:Query('SELECT code, name, description, sales FROM test') - - aStruct := oQuery:Struct() - - For i := 1 to Len(aStruct) - ? aStruct[i,1], aStruct[i,2], aStruct[i,3], aStruct[i,4] - Next - - aKey := oQuery:GetKeyField() - - ? "Fields: ", oQuery:Fcount(), "Primary Key: ", aKey[1] - - oRow := oQuery:Blank() - - ? oRow:FCount(), ; - oRow:Fieldpos('code'), ; - oRow:Fieldget(1), ; - oRow:Fieldname(1), ; - oRow:Fieldtype(1), ; - oRow:Fielddec(1), ; - oRow:Fieldlen(1), ; - len(oRow:Getkeyfield()) - - oRow:Fieldput(1, 150) - oRow:Fieldput(2, 'MY TEST') - - ? oRow:Fieldget(1), oRow:Fieldget(2) - - ? oServer:Append(oRow) - - ? oServer:Delete(oQuery:blank(), 'code = 200') - - ? oServer:Execute('error caused intentionaly') - - DO WHILE ! oQuery:Eof() - oQuery:Skip() - ? oQuery:Fieldget(oQuery:Fieldpos('code')), ; - oQuery:Fieldget(4), ; - oQuery:Fieldget(2), ; - oQuery:Fieldname(1),; - oQuery:Fieldtype(1), ; - oQuery:Fielddec(1), ; - oQuery:Fieldlen(1),; - oQuery:Fieldget(3) - - if oQuery:Recno() == 50 - oRow := oQuery:getrow() - - oRow:Fieldput(2, 'My Second test') - ? 'Update: ', oServer:Update(oRow) - end - - if oQuery:Recno() == 60 - oRow := oQuery:getrow() - ? 'Delete: ', oServer:Delete(oRow) - end - END - - ? 'Delete: ', oServer:Delete(oQuery:Blank(), 'code = 70') - - oQuery:Refresh() - - DO WHILE oQuery:Fetch() - oRow := oQuery:getrow() - - ? oRow:Fieldget(oRow:Fieldpos('code')), ; - oRow:Fieldget(4), ; - oRow:Fieldget(2), ; - oRow:Fieldname(1),; - oRow:Fieldtype(1), ; - oRow:Fielddec(1), ; - oRow:Fieldlen(1),; - oRow:Fieldget(3) - END - - oQuery:Destroy() - - oServer:Destroy() - - - ? "Closing..." - - return nil - - - +/* + * $Id$ + */ + +#include "common.ch" + +Function main() + Local oServer, oQuery, oRow, i, x, aTables, aStruct, aKey + + Local cServer := '192.168.1.33:D:\firebird\test\test.gdb' + Local cUser := 'sysdba' + Local cPass := 'masterkey' + Local nDialect := 1 + Local cQuery + + if File('test.gdb') + FErase('test.gdb') + end + + ? FBCreateDB('test.gdb', cuser, cpass, 1024, 'ASCII', nDialect ) + + ? "Connecting..." + + oServer := TFBServer():New(cServer, cUser, cPass, nDialect) + + if oServer:NetErr() + ? oServer:Error() + quit + end + + ? 'Tables...' + + For x := 1 to 1 + aTables := oServer:ListTables() + + For i := 1 to Len(aTables) + ? aTables[i] + next + Next + + ? 'Using implicit transaction...' + + if oServer:TableExists('TEST') + oServer:Execute('DROP TABLE Test') + oServer:Execute('DROP DOMAIN boolean_field') + end + + ? 'Creating domain for boolean fields...' + oServer:Execute('create domain boolean_field as smallint default 0 not null check (value in (0,1))') + + oServer:StartTransaction() + ? 'Creating test table...' + cQuery := 'CREATE TABLE test(' + cQuery += ' Code SmallInt not null primary key, ' + cQuery += ' dept Integer, ' + cQuery += ' Name Varchar(40), ' + cQuery += ' Sales boolean_field, ' + cQuery += ' Tax Float, ' + cQuery += ' Salary Double Precision, ' + cQuery += ' Budget Numeric(12,2), ' + cQuery += ' Discount Decimal(5,2), ' + cQuery += ' Creation Date, ' + cQuery += ' Description blob sub_type 1 segment size 40 ) ' + + oServer:Execute(cQuery) + + if oServer:neterr() + ? oServer:Error() + end + + oServer:Commit() + + oQuery := oServer:Query('SELECT code, dept, name, sales, salary, creation FROM test') + wait + + + ? 'Structure of test table' + aStruct := oServer:TableStruct('test') + + For i := 1 to Len(aStruct) + ? + For x := 1 to Len(aStruct[i]) + ?? aStruct[i,x] + Next + next + + ? 'Inserting, declared transaction control ' + oServer:StartTransaction() + + For i := 1 to 100 + cQuery := 'INSERT INTO test(code, dept, name, sales, tax, salary, budget, Discount, Creation, Description) ' + cQuery += 'VALUES( ' + str(i) + ', 2, "TEST", 1, 5, 3000, 1500.2, 7.5, "12-22-2003", "Short Description about what ? ")' + + oServer:Execute(cQuery) + + if oServer:neterr() + ? oServer:error() + end + Next + + oServer:Commit() + + oQuery := oServer:Query('SELECT code, name, description, sales FROM test') + + aStruct := oQuery:Struct() + + For i := 1 to Len(aStruct) + ? aStruct[i,1], aStruct[i,2], aStruct[i,3], aStruct[i,4] + Next + + aKey := oQuery:GetKeyField() + + ? "Fields: ", oQuery:Fcount(), "Primary Key: ", aKey[1] + + oRow := oQuery:Blank() + + ? oRow:FCount(), ; + oRow:Fieldpos('code'), ; + oRow:Fieldget(1), ; + oRow:Fieldname(1), ; + oRow:Fieldtype(1), ; + oRow:Fielddec(1), ; + oRow:Fieldlen(1), ; + len(oRow:Getkeyfield()) + + oRow:Fieldput(1, 150) + oRow:Fieldput(2, 'MY TEST') + + ? oRow:Fieldget(1), oRow:Fieldget(2) + + ? oServer:Append(oRow) + + ? oServer:Delete(oQuery:blank(), 'code = 200') + + ? oServer:Execute('error caused intentionaly') + + DO WHILE ! oQuery:Eof() + oQuery:Skip() + ? oQuery:Fieldget(oQuery:Fieldpos('code')), ; + oQuery:Fieldget(4), ; + oQuery:Fieldget(2), ; + oQuery:Fieldname(1),; + oQuery:Fieldtype(1), ; + oQuery:Fielddec(1), ; + oQuery:Fieldlen(1),; + oQuery:Fieldget(3) + + if oQuery:Recno() == 50 + oRow := oQuery:getrow() + + oRow:Fieldput(2, 'My Second test') + ? 'Update: ', oServer:Update(oRow) + end + + if oQuery:Recno() == 60 + oRow := oQuery:getrow() + ? 'Delete: ', oServer:Delete(oRow) + end + END + + ? 'Delete: ', oServer:Delete(oQuery:Blank(), 'code = 70') + + oQuery:Refresh() + + DO WHILE oQuery:Fetch() + oRow := oQuery:getrow() + + ? oRow:Fieldget(oRow:Fieldpos('code')), ; + oRow:Fieldget(4), ; + oRow:Fieldget(2), ; + oRow:Fieldname(1),; + oRow:Fieldtype(1), ; + oRow:Fielddec(1), ; + oRow:Fieldlen(1),; + oRow:Fieldget(3) + END + + oQuery:Destroy() + + oServer:Destroy() + + + ? "Closing..." + + return nil + + + diff --git a/harbour/contrib/firebird/test/stress.prg b/harbour/contrib/firebird/test/stress.prg index 2c48342bf0..f732c456ac 100644 --- a/harbour/contrib/firebird/test/stress.prg +++ b/harbour/contrib/firebird/test/stress.prg @@ -1,134 +1,134 @@ -/* - * $Id: atrepl.c 7583 2007-07-06 21:17:36Z druzus $ - */ - -/* VERY IMPORTANT: Don't use this querys as sample, they are used for stress tests !!! */ - -Function Main() - Local oServer, oQuery, oRow, i, x - - Local cServer := '192.168.1.33:D:\firebird\test\test2.gdb' - Local cUser := 'sysdba' - Local cPass := 'masterkey' - Local nDialect := 1 - Local cQuery - - CLEAR SCREEN - - if ! File('test2.gdb') .and. .F. - ? FBCreateDB('test2.gdb', cuser, cpass, 1024, 'WIN1251', nDialect ) - end - - ? "Connecting..." - - oServer := TFBServer():New(cServer, cUser, cPass, nDialect) - - if oServer:NetErr() - ? oServer:Error() - quit - end - - if oServer:TableExists('test') - ? oServer:Execute('DROP TABLE Test') - ? oServer:Execute('DROP DOMAIN boolean_field') - end - - ? 'Creating domain for boolean fields...' - - ? oServer:Execute('create domain boolean_field as smallint default 0 not null check (value in (0,1))') - - ? 'Creating test table...' - cQuery := 'CREATE TABLE test(' - cQuery += ' Code SmallInt not null primary key, ' - cQuery += ' dept Integer, ' - cQuery += ' Name Varchar(40), ' - cQuery += ' Sales boolean_field, ' - cQuery += ' Tax Float, ' - cQuery += ' Salary Double Precision, ' - cQuery += ' Budget Numeric(12,2), ' - cQuery += ' Discount Decimal(5,2), ' - cQuery += ' Creation Date, ' - cQuery += ' Description blob sub_type 1 segment size 40 ) ' - - ? oServer:Execute(cQuery) - -quit - - oQuery := oServer:Query('SELECT code, dept, name, sales, salary, creation FROM test') - - oServer:StartTransaction() - - For i := 1 to 10000 - @ 15,0 say 'Inserting values....' + str(i) - - oRow := oQuery:Blank() - - oRow:Fieldput(1, i) - oRow:Fieldput(2, i+1) - oRow:Fieldput(3, 'DEPARTMENT NAME ' + strzero(i) ) - oRow:Fieldput(4, (mod(i,10) == 0) ) - oRow:Fieldput(5, 3000 + i ) - oRow:fieldput(6, Date() ) - - oServer:Append(oRow) - - if mod(i,100) == 0 - oServer:Commit() - oServer:StartTransaction() - end - Next - - For i := 5000 to 7000 - @ 16,0 say 'Deleting values....' + str(i) - - oRow := oQuery:Blank() - oServer:Delete(oRow, 'code = ' + str(i)) - - if mod(i,100) == 0 - oServer:Commit() - oServer:StartTransaction() - end - Next - - For i := 2000 to 3000 - @ 17,0 say 'Updating values....' + str(i) - - oRow := oQuery:Blank() - oRow:Fieldput(5, 4000+i) - oServer:update(oRow, 'code = ' + str(i)) - - if mod(i,100) == 0 - oServer:Commit() - oServer:StartTransaction() - end - Next - - oQuery := oServer:Query('SELECT sum(salary) sum_salary FROM test WHERE code between 1 and 4000') - - if ! oQuery:Neterr() - oQuery:Fetch() - @ 18,0 say 'Sum values....' + Str(oQuery:Fieldget(1)) - oQuery:Destroy() - end - - - x := 0 - For i := 1 to 4000 - oQuery := oServer:Query('SELECT * FROM test WHERE code = ' + str(i)) - - if ! oQuery:Neterr() - oQuery:Fetch() - oRow := oQuery:getrow() - - oQuery:destroy() - x += oRow:fieldget(oRow:fieldpos('salary')) - - @ 19,0 say 'Sum values....' + str(x) - end - Next - - - oServer:Destroy() - - ? "Closing..." -return nil +/* + * $Id$ + */ + +/* VERY IMPORTANT: Don't use this querys as sample, they are used for stress tests !!! */ + +Function Main() + Local oServer, oQuery, oRow, i, x + + Local cServer := '192.168.1.33:D:\firebird\test\test2.gdb' + Local cUser := 'sysdba' + Local cPass := 'masterkey' + Local nDialect := 1 + Local cQuery + + CLEAR SCREEN + + if ! File('test2.gdb') .and. .F. + ? FBCreateDB('test2.gdb', cuser, cpass, 1024, 'WIN1251', nDialect ) + end + + ? "Connecting..." + + oServer := TFBServer():New(cServer, cUser, cPass, nDialect) + + if oServer:NetErr() + ? oServer:Error() + quit + end + + if oServer:TableExists('test') + ? oServer:Execute('DROP TABLE Test') + ? oServer:Execute('DROP DOMAIN boolean_field') + end + + ? 'Creating domain for boolean fields...' + + ? oServer:Execute('create domain boolean_field as smallint default 0 not null check (value in (0,1))') + + ? 'Creating test table...' + cQuery := 'CREATE TABLE test(' + cQuery += ' Code SmallInt not null primary key, ' + cQuery += ' dept Integer, ' + cQuery += ' Name Varchar(40), ' + cQuery += ' Sales boolean_field, ' + cQuery += ' Tax Float, ' + cQuery += ' Salary Double Precision, ' + cQuery += ' Budget Numeric(12,2), ' + cQuery += ' Discount Decimal(5,2), ' + cQuery += ' Creation Date, ' + cQuery += ' Description blob sub_type 1 segment size 40 ) ' + + ? oServer:Execute(cQuery) + +quit + + oQuery := oServer:Query('SELECT code, dept, name, sales, salary, creation FROM test') + + oServer:StartTransaction() + + For i := 1 to 10000 + @ 15,0 say 'Inserting values....' + str(i) + + oRow := oQuery:Blank() + + oRow:Fieldput(1, i) + oRow:Fieldput(2, i+1) + oRow:Fieldput(3, 'DEPARTMENT NAME ' + strzero(i) ) + oRow:Fieldput(4, (mod(i,10) == 0) ) + oRow:Fieldput(5, 3000 + i ) + oRow:fieldput(6, Date() ) + + oServer:Append(oRow) + + if mod(i,100) == 0 + oServer:Commit() + oServer:StartTransaction() + end + Next + + For i := 5000 to 7000 + @ 16,0 say 'Deleting values....' + str(i) + + oRow := oQuery:Blank() + oServer:Delete(oRow, 'code = ' + str(i)) + + if mod(i,100) == 0 + oServer:Commit() + oServer:StartTransaction() + end + Next + + For i := 2000 to 3000 + @ 17,0 say 'Updating values....' + str(i) + + oRow := oQuery:Blank() + oRow:Fieldput(5, 4000+i) + oServer:update(oRow, 'code = ' + str(i)) + + if mod(i,100) == 0 + oServer:Commit() + oServer:StartTransaction() + end + Next + + oQuery := oServer:Query('SELECT sum(salary) sum_salary FROM test WHERE code between 1 and 4000') + + if ! oQuery:Neterr() + oQuery:Fetch() + @ 18,0 say 'Sum values....' + Str(oQuery:Fieldget(1)) + oQuery:Destroy() + end + + + x := 0 + For i := 1 to 4000 + oQuery := oServer:Query('SELECT * FROM test WHERE code = ' + str(i)) + + if ! oQuery:Neterr() + oQuery:Fetch() + oRow := oQuery:getrow() + + oQuery:destroy() + x += oRow:fieldget(oRow:fieldpos('salary')) + + @ 19,0 say 'Sum values....' + str(x) + end + Next + + + oServer:Destroy() + + ? "Closing..." +return nil diff --git a/harbour/contrib/firebird/test/test.prg b/harbour/contrib/firebird/test/test.prg index df803ac5c8..b520df4702 100644 --- a/harbour/contrib/firebird/test/test.prg +++ b/harbour/contrib/firebird/test/test.prg @@ -1,77 +1,77 @@ -/* - * $Id: atrepl.c 7583 2007-07-06 21:17:36Z druzus $ - */ - -#include "common.ch" - -Function Main() - - nDialect := 1 - - if File('test.gdb') - FErase('test.gdb') - end - - ? FBCreateDB('test.gdb','sysdba', 'masterkey', 1024, 'ASCII', nDialect ) - - - /* Connect rdbms */ - db := FBConnect("127.0.0.1:d:\firebird\test\test.gdb", "sysdba", "masterkey") - - if ISNUMBER(db) - ? 'Error' - quit - end - - ? FBExecute(db, 'sldjfs;ldjs;djf', dialect) - - ? FBClose(db) - - trans := FBStartTransaction(db) - qry := FBQuery(db, 'create table teste (code smallint)', dialect, trans) - FBCommit(trans) - - - ? "Status Execute: ", FBExecute( db, 'insert into customer(customer) values ("test 1")', dialect, trans) - - ? "Status no Rollback: ", FBRollback(trans) - - trans := FBStartTransaction(db) - ? "Status Execute: ", FBExecute( db, 'insert into customer(customer) values ("test 2")', dialect, trans ) - ? "Status commit: ", FBCommit(trans) - - - ? "Status Execute: ", FBExecute( db, 'insert into customer(customer) values ("test 3")', dialect ) - - // FIX WINDOWS GPF BELOW - - qry := FBQuery(db, "SELECT * FROM sales", dialect) - - num_cols := qry[4] - columns := qry[6] - - For x := 1 to num_cols - ? x, "> " - For y := 1 to len(columns[x]) - ?? columns[x,y], ' ' - Next - Next - - ? '---' - - do while (fetch_stat := FBFetch(qry)) == 0 - ? fetch_stat - for x := 1 to num_cols - ?? FBGetData(qry,x), ', ' - next - end - - ? 'Fetch code:', fetch_stat - - ? "Status Free sql: ", FBFree(qry) - - - /* Close connection with rdbms */ - ? "Status Fechar Database: ", FBClose(db) - - Return Nil +/* + * $Id$ + */ + +#include "common.ch" + +Function Main() + + nDialect := 1 + + if File('test.gdb') + FErase('test.gdb') + end + + ? FBCreateDB('test.gdb','sysdba', 'masterkey', 1024, 'ASCII', nDialect ) + + + /* Connect rdbms */ + db := FBConnect("127.0.0.1:d:\firebird\test\test.gdb", "sysdba", "masterkey") + + if ISNUMBER(db) + ? 'Error' + quit + end + + ? FBExecute(db, 'sldjfs;ldjs;djf', dialect) + + ? FBClose(db) + + trans := FBStartTransaction(db) + qry := FBQuery(db, 'create table teste (code smallint)', dialect, trans) + FBCommit(trans) + + + ? "Status Execute: ", FBExecute( db, 'insert into customer(customer) values ("test 1")', dialect, trans) + + ? "Status no Rollback: ", FBRollback(trans) + + trans := FBStartTransaction(db) + ? "Status Execute: ", FBExecute( db, 'insert into customer(customer) values ("test 2")', dialect, trans ) + ? "Status commit: ", FBCommit(trans) + + + ? "Status Execute: ", FBExecute( db, 'insert into customer(customer) values ("test 3")', dialect ) + + // FIX WINDOWS GPF BELOW + + qry := FBQuery(db, "SELECT * FROM sales", dialect) + + num_cols := qry[4] + columns := qry[6] + + For x := 1 to num_cols + ? x, "> " + For y := 1 to len(columns[x]) + ?? columns[x,y], ' ' + Next + Next + + ? '---' + + do while (fetch_stat := FBFetch(qry)) == 0 + ? fetch_stat + for x := 1 to num_cols + ?? FBGetData(qry,x), ', ' + next + end + + ? 'Fetch code:', fetch_stat + + ? "Status Free sql: ", FBFree(qry) + + + /* Close connection with rdbms */ + ? "Status Fechar Database: ", FBClose(db) + + Return Nil diff --git a/harbour/contrib/firebird/test/testapi.c b/harbour/contrib/firebird/test/testapi.c index f6656a2813..2d88e1bdff 100644 --- a/harbour/contrib/firebird/test/testapi.c +++ b/harbour/contrib/firebird/test/testapi.c @@ -1,403 +1,403 @@ -/* - * $Id: atrepl.c 7583 2007-07-06 21:17:36Z druzus $ - */ - -#include -#include -#include -#include -#include -#include - -#ifndef ISC_INT64_FORMAT - -#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__BORLANDC__) && defined(__WIN32__)) -#define ISC_INT64_FORMAT "I64" -#else -#define ISC_INT64_FORMAT "ll" -#endif -#endif - -#define USER "sysdba" -#define PASSWORD "masterkey" -#define DATABASE "192.168.1.33:d:\\fontes\\lixo\\test.gdb" -#define ERREXIT(status, rc) {isc_print_status(status); return rc;} -#define MAX_BUFFER 1024 - -int execute( char *exec_str ); -int query( char *sel_str ); -int fetch( void ); -int qclose( void ); -char *getdata(int pos); - - -isc_db_handle db = NULL; -int dialect = 1; -XSQLDA ISC_FAR * sqlda; -isc_stmt_handle stmt = NULL; -isc_tr_handle trans = NULL; - -int main () -{ - char dpb[48]; - int i = 0, len; - long status[20]; - - dpb[i++] = isc_dpb_version1; - - dpb[i++] = isc_dpb_user_name; - len = strlen(USER); - dpb[i++] = (char) len; - strncpy(&(dpb[i]), USER, len); - i += len; - - dpb[i++] = isc_dpb_password; - len = strlen (PASSWORD); - dpb[i++] = len; - strncpy(&(dpb[i]), PASSWORD, len); - i += len; - - if (isc_attach_database(status, 0, DATABASE, &db, i, dpb)) - ERREXIT(status, 1); - - execute("DROP TABLE TESTE"); - - execute("CREATE TABLE TESTE (code smallint)"); - - execute("INSERT INTO TESTE (code) VALUES (100)"); - - query("SELECT * FROM TESTE"); - while (fetch() == 0) - printf("%s\n", getdata(0)); - qclose(); - - - if (isc_detach_database(status, &db)) - ERREXIT(status, 1); - - return 1; -} - -int execute( char *exec_str ) -{ - isc_tr_handle trans = NULL; - long status[20]; - - if (isc_start_transaction(status, &trans, 1, &db, 0, NULL)) - ERREXIT(status, 1); - - if (isc_dsql_execute_immediate(status, &db, &trans, 0, exec_str, dialect, NULL)) - ERREXIT(status, 1); - - if (isc_commit_transaction(status, &trans)) - ERREXIT(status, 1); - - return 1; -} - -int query( char *sel_str ) -{ - ISC_STATUS status[20]; - XSQLVAR *var; - - int n, i, dtype; - - if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) - ERREXIT(status, 1); - - // Allocate an output SQLDA. Just to check number of columns - sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH ( 1 ) ); - sqlda->sqln = 1; - sqlda->version = 1; - - // Allocate a statement - if (isc_dsql_allocate_statement(status, &db, &stmt)) - ERREXIT(status, 1); - - // Prepare the statement. - if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, dialect, sqlda)) - ERREXIT(status, 1); - - // Describe sql contents - if (isc_dsql_describe(status, &stmt, dialect, sqlda)) - ERREXIT(status, 1); - - // Relocate necessary number of columns - if ( sqlda->sqld > sqlda->sqln ) { - free( sqlda ); - n = sqlda->sqld; - sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH ( n ) ); - sqlda->sqln = n; - sqlda->version = 1; - - if (isc_dsql_describe(status, &stmt, dialect, sqlda)) - ERREXIT(status, 1); - } - - for ( i = 0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++ ) { - dtype = ( var->sqltype & ~1 ); - switch ( dtype ) { - case SQL_VARYING: - var->sqltype = SQL_TEXT; - var->sqldata = ( char * ) malloc( sizeof ( char ) * var->sqllen + 2 ); - break; - case SQL_TEXT: - var->sqldata = ( char * ) malloc( sizeof ( char ) * var->sqllen + 2 ); - break; - case SQL_LONG: - var->sqltype = SQL_LONG; - var->sqldata = ( char * ) malloc( sizeof ( long ) ); - break; - default: - var->sqldata = ( char * ) malloc( sizeof ( char ) * var->sqllen ); - break; - } - if ( var->sqltype & 1 ) { - var->sqlind = ( short * ) malloc( sizeof ( short ) ); - } - } - - if ( !sqlda->sqld ) { - // Execute and commit non-select querys - if ( isc_dsql_execute ( status, &trans, &stmt, dialect, NULL ) ) - ERREXIT(status, 1); - - if (isc_commit_transaction(status, &trans)) - ERREXIT(status, 1); - - trans = NULL; - - } else { - if ( isc_dsql_execute ( status, &trans, &stmt, dialect, sqlda ) ) - ERREXIT(status, 1); - } - - return 1; -} - -int fetch( void ) -{ - long fetch_stat; - long status[20]; - - fetch_stat = isc_dsql_fetch(status, &stmt, dialect, sqlda); - - if (fetch_stat != 100L) - ERREXIT(status, 1); - - return fetch_stat; -} - -int qclose( void ) -{ - long status[20]; - - if (isc_dsql_free_statement(status, &stmt, DSQL_drop)) - ERREXIT(status, 1); - - if (trans) - if (isc_commit_transaction(status, &trans)) - ERREXIT(status, 1); - - if ( sqlda ) - free( sqlda ); - - return 1; -} - -char *getdata(int pos) -{ - short dtype; - char data[MAX_BUFFER], *p; - char blob_s[20], date_s[25]; - short len; - long status[20]; - - struct tm times; - ISC_QUAD bid; - XSQLVAR *var; - - if ( ( pos + 1 ) > sqlda->sqln ) - return "error"; - - var = sqlda->sqlvar; - - var += pos; - - dtype = var->sqltype & ~1; - p = data; - - if ( ( var->sqltype & 1 ) && ( *var->sqlind < 0 ) ) { - switch ( dtype ) { - case SQL_TEXT: - case SQL_VARYING: - len = var->sqllen; - break; - case SQL_SHORT: - len = 6; - if ( var->sqlscale > 0 ) - len += var->sqlscale; - break; - case SQL_LONG: - len = 11; - if ( var->sqlscale > 0 ) - len += var->sqlscale; - break; - case SQL_INT64: - len = 21; - if ( var->sqlscale > 0 ) - len += var->sqlscale; - break; - case SQL_FLOAT: - len = 15; - break; - case SQL_DOUBLE: - len = 24; - break; - case SQL_TIMESTAMP: - len = 24; - break; - case SQL_TYPE_DATE: - len = 10; - break; - case SQL_TYPE_TIME: - len = 13; - break; - case SQL_BLOB: - case SQL_ARRAY: - default: - len = 17; - break; - } - if ( ( dtype == SQL_TEXT ) || ( dtype == SQL_VARYING ) ) - sprintf ( p, "%-*s ", len, "NULL" ); - else - sprintf ( p, "%*s ", len, "NULL" ); - } else { - switch ( dtype ) { - case SQL_TEXT: - sprintf ( p, "%.*s ", var->sqllen, var->sqldata ); - break; - - case SQL_VARYING: - sprintf ( p, "%.*s ", var->sqllen, var->sqldata ); - break; - - case SQL_SHORT: - case SQL_LONG: - case SQL_INT64: - { - ISC_INT64 value = 0; - short field_width = 0; - short dscale; - - switch ( dtype ) { - case SQL_SHORT: - value = ( ISC_INT64 ) * ( short ISC_FAR * ) var->sqldata; - field_width = 6; - break; - case SQL_LONG: - value = ( ISC_INT64 ) * ( long ISC_FAR * ) var->sqldata; - field_width = 11; - break; - case SQL_INT64: - value = ( ISC_INT64 ) * ( ISC_INT64 ISC_FAR * ) var->sqldata; - field_width = 21; - break; - } - dscale = var->sqlscale; - if ( dscale < 0 ) { - ISC_INT64 tens; - short i; - - tens = 1; - for ( i = 0; i > dscale; i-- ) { - tens *= 10; - - if ( value >= 0 ) { - - sprintf ( p, - "%*" ISC_INT64_FORMAT "d.%0*" - ISC_INT64_FORMAT "d", - field_width - 1 + dscale, - ( ISC_INT64 ) ( value / tens ), -dscale, - ( ISC_INT64 ) ( value % tens ) ); - } else if ( ( value / tens ) != 0 ) { - - sprintf ( p, - "%*" ISC_INT64_FORMAT "d.%0*" - ISC_INT64_FORMAT "d", - field_width - 1 + dscale, - ( ISC_INT64 ) ( value / tens ), -dscale, - ( ISC_INT64 ) - ( value % tens ) ); - } else { - - sprintf ( p, "%*s.%0*" ISC_INT64_FORMAT "d", - field_width - 1 + dscale, - "-0", -dscale, - ( ISC_INT64 ) - ( value % tens ) ); - } - } - } else if ( dscale ) { - sprintf ( p, "%*" ISC_INT64_FORMAT "d%0*d", - field_width, ( ISC_INT64 ) value, dscale, 0 ); - } else { - sprintf ( p, "%*" ISC_INT64_FORMAT "d", - field_width, ( ISC_INT64 ) value ); - } - }; - break; - - case SQL_FLOAT: - sprintf ( p, "%15g ", *( float ISC_FAR * ) ( var->sqldata ) ); - break; - - case SQL_DOUBLE: - sprintf ( p, "%24f ", *( double ISC_FAR * ) ( var->sqldata ) ); - break; - - case SQL_TIMESTAMP: - isc_decode_timestamp ( ( ISC_TIMESTAMP ISC_FAR * ) var->sqldata, × ); - sprintf ( date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04lui", - times.tm_year + 1900, - times.tm_mon + 1, - times.tm_mday, - times.tm_hour, - times.tm_min, - times.tm_sec, - ( ( ISC_TIMESTAMP * ) var->sqldata )->timestamp_time % 10000 ); - sprintf ( p, "%*s ", 24, date_s ); - break; - - case SQL_TYPE_DATE: - isc_decode_sql_date ( ( ISC_DATE ISC_FAR * ) var->sqldata, × ); - sprintf ( date_s, "%04d-%02d-%02d", - times.tm_year + 1900, times.tm_mon + 1, times.tm_mday ); - sprintf ( p, "%*s ", 10, date_s ); - break; - - case SQL_TYPE_TIME: - isc_decode_sql_time ( ( ISC_TIME ISC_FAR * ) var->sqldata, × ); - sprintf ( date_s, "%02d:%02d:%02d.%04lui", - times.tm_hour, - times.tm_min, - times.tm_sec, ( *( ( ISC_TIME * ) var->sqldata ) ) % 10000 ); - sprintf ( p, "%*s ", 13, date_s ); - break; - - case SQL_BLOB: - case SQL_ARRAY: - /* Print the blob id on blobs or arrays */ - bid = *( ISC_QUAD ISC_FAR * ) var->sqldata; - sprintf ( blob_s, "%08x:%08x", ( unsigned int ) bid.gds_quad_high, - ( unsigned int ) bid.gds_quad_low ); - sprintf ( p, "%17s ", blob_s ); - break; - - default: - break; - } - } - - return ( p ); -} +/* + * $Id$ + */ + +#include +#include +#include +#include +#include +#include + +#ifndef ISC_INT64_FORMAT + +#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__BORLANDC__) && defined(__WIN32__)) +#define ISC_INT64_FORMAT "I64" +#else +#define ISC_INT64_FORMAT "ll" +#endif +#endif + +#define USER "sysdba" +#define PASSWORD "masterkey" +#define DATABASE "192.168.1.33:d:\\fontes\\lixo\\test.gdb" +#define ERREXIT(status, rc) {isc_print_status(status); return rc;} +#define MAX_BUFFER 1024 + +int execute( char *exec_str ); +int query( char *sel_str ); +int fetch( void ); +int qclose( void ); +char *getdata(int pos); + + +isc_db_handle db = NULL; +int dialect = 1; +XSQLDA ISC_FAR * sqlda; +isc_stmt_handle stmt = NULL; +isc_tr_handle trans = NULL; + +int main () +{ + char dpb[48]; + int i = 0, len; + long status[20]; + + dpb[i++] = isc_dpb_version1; + + dpb[i++] = isc_dpb_user_name; + len = strlen(USER); + dpb[i++] = (char) len; + strncpy(&(dpb[i]), USER, len); + i += len; + + dpb[i++] = isc_dpb_password; + len = strlen (PASSWORD); + dpb[i++] = len; + strncpy(&(dpb[i]), PASSWORD, len); + i += len; + + if (isc_attach_database(status, 0, DATABASE, &db, i, dpb)) + ERREXIT(status, 1); + + execute("DROP TABLE TESTE"); + + execute("CREATE TABLE TESTE (code smallint)"); + + execute("INSERT INTO TESTE (code) VALUES (100)"); + + query("SELECT * FROM TESTE"); + while (fetch() == 0) + printf("%s\n", getdata(0)); + qclose(); + + + if (isc_detach_database(status, &db)) + ERREXIT(status, 1); + + return 1; +} + +int execute( char *exec_str ) +{ + isc_tr_handle trans = NULL; + long status[20]; + + if (isc_start_transaction(status, &trans, 1, &db, 0, NULL)) + ERREXIT(status, 1); + + if (isc_dsql_execute_immediate(status, &db, &trans, 0, exec_str, dialect, NULL)) + ERREXIT(status, 1); + + if (isc_commit_transaction(status, &trans)) + ERREXIT(status, 1); + + return 1; +} + +int query( char *sel_str ) +{ + ISC_STATUS status[20]; + XSQLVAR *var; + + int n, i, dtype; + + if ( isc_start_transaction ( status, &trans, 1, &db, 0, NULL ) ) + ERREXIT(status, 1); + + // Allocate an output SQLDA. Just to check number of columns + sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH ( 1 ) ); + sqlda->sqln = 1; + sqlda->version = 1; + + // Allocate a statement + if (isc_dsql_allocate_statement(status, &db, &stmt)) + ERREXIT(status, 1); + + // Prepare the statement. + if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, dialect, sqlda)) + ERREXIT(status, 1); + + // Describe sql contents + if (isc_dsql_describe(status, &stmt, dialect, sqlda)) + ERREXIT(status, 1); + + // Relocate necessary number of columns + if ( sqlda->sqld > sqlda->sqln ) { + free( sqlda ); + n = sqlda->sqld; + sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH ( n ) ); + sqlda->sqln = n; + sqlda->version = 1; + + if (isc_dsql_describe(status, &stmt, dialect, sqlda)) + ERREXIT(status, 1); + } + + for ( i = 0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++ ) { + dtype = ( var->sqltype & ~1 ); + switch ( dtype ) { + case SQL_VARYING: + var->sqltype = SQL_TEXT; + var->sqldata = ( char * ) malloc( sizeof ( char ) * var->sqllen + 2 ); + break; + case SQL_TEXT: + var->sqldata = ( char * ) malloc( sizeof ( char ) * var->sqllen + 2 ); + break; + case SQL_LONG: + var->sqltype = SQL_LONG; + var->sqldata = ( char * ) malloc( sizeof ( long ) ); + break; + default: + var->sqldata = ( char * ) malloc( sizeof ( char ) * var->sqllen ); + break; + } + if ( var->sqltype & 1 ) { + var->sqlind = ( short * ) malloc( sizeof ( short ) ); + } + } + + if ( !sqlda->sqld ) { + // Execute and commit non-select querys + if ( isc_dsql_execute ( status, &trans, &stmt, dialect, NULL ) ) + ERREXIT(status, 1); + + if (isc_commit_transaction(status, &trans)) + ERREXIT(status, 1); + + trans = NULL; + + } else { + if ( isc_dsql_execute ( status, &trans, &stmt, dialect, sqlda ) ) + ERREXIT(status, 1); + } + + return 1; +} + +int fetch( void ) +{ + long fetch_stat; + long status[20]; + + fetch_stat = isc_dsql_fetch(status, &stmt, dialect, sqlda); + + if (fetch_stat != 100L) + ERREXIT(status, 1); + + return fetch_stat; +} + +int qclose( void ) +{ + long status[20]; + + if (isc_dsql_free_statement(status, &stmt, DSQL_drop)) + ERREXIT(status, 1); + + if (trans) + if (isc_commit_transaction(status, &trans)) + ERREXIT(status, 1); + + if ( sqlda ) + free( sqlda ); + + return 1; +} + +char *getdata(int pos) +{ + short dtype; + char data[MAX_BUFFER], *p; + char blob_s[20], date_s[25]; + short len; + long status[20]; + + struct tm times; + ISC_QUAD bid; + XSQLVAR *var; + + if ( ( pos + 1 ) > sqlda->sqln ) + return "error"; + + var = sqlda->sqlvar; + + var += pos; + + dtype = var->sqltype & ~1; + p = data; + + if ( ( var->sqltype & 1 ) && ( *var->sqlind < 0 ) ) { + switch ( dtype ) { + case SQL_TEXT: + case SQL_VARYING: + len = var->sqllen; + break; + case SQL_SHORT: + len = 6; + if ( var->sqlscale > 0 ) + len += var->sqlscale; + break; + case SQL_LONG: + len = 11; + if ( var->sqlscale > 0 ) + len += var->sqlscale; + break; + case SQL_INT64: + len = 21; + if ( var->sqlscale > 0 ) + len += var->sqlscale; + break; + case SQL_FLOAT: + len = 15; + break; + case SQL_DOUBLE: + len = 24; + break; + case SQL_TIMESTAMP: + len = 24; + break; + case SQL_TYPE_DATE: + len = 10; + break; + case SQL_TYPE_TIME: + len = 13; + break; + case SQL_BLOB: + case SQL_ARRAY: + default: + len = 17; + break; + } + if ( ( dtype == SQL_TEXT ) || ( dtype == SQL_VARYING ) ) + sprintf ( p, "%-*s ", len, "NULL" ); + else + sprintf ( p, "%*s ", len, "NULL" ); + } else { + switch ( dtype ) { + case SQL_TEXT: + sprintf ( p, "%.*s ", var->sqllen, var->sqldata ); + break; + + case SQL_VARYING: + sprintf ( p, "%.*s ", var->sqllen, var->sqldata ); + break; + + case SQL_SHORT: + case SQL_LONG: + case SQL_INT64: + { + ISC_INT64 value = 0; + short field_width = 0; + short dscale; + + switch ( dtype ) { + case SQL_SHORT: + value = ( ISC_INT64 ) * ( short ISC_FAR * ) var->sqldata; + field_width = 6; + break; + case SQL_LONG: + value = ( ISC_INT64 ) * ( long ISC_FAR * ) var->sqldata; + field_width = 11; + break; + case SQL_INT64: + value = ( ISC_INT64 ) * ( ISC_INT64 ISC_FAR * ) var->sqldata; + field_width = 21; + break; + } + dscale = var->sqlscale; + if ( dscale < 0 ) { + ISC_INT64 tens; + short i; + + tens = 1; + for ( i = 0; i > dscale; i-- ) { + tens *= 10; + + if ( value >= 0 ) { + + sprintf ( p, + "%*" ISC_INT64_FORMAT "d.%0*" + ISC_INT64_FORMAT "d", + field_width - 1 + dscale, + ( ISC_INT64 ) ( value / tens ), -dscale, + ( ISC_INT64 ) ( value % tens ) ); + } else if ( ( value / tens ) != 0 ) { + + sprintf ( p, + "%*" ISC_INT64_FORMAT "d.%0*" + ISC_INT64_FORMAT "d", + field_width - 1 + dscale, + ( ISC_INT64 ) ( value / tens ), -dscale, + ( ISC_INT64 ) - ( value % tens ) ); + } else { + + sprintf ( p, "%*s.%0*" ISC_INT64_FORMAT "d", + field_width - 1 + dscale, + "-0", -dscale, + ( ISC_INT64 ) - ( value % tens ) ); + } + } + } else if ( dscale ) { + sprintf ( p, "%*" ISC_INT64_FORMAT "d%0*d", + field_width, ( ISC_INT64 ) value, dscale, 0 ); + } else { + sprintf ( p, "%*" ISC_INT64_FORMAT "d", + field_width, ( ISC_INT64 ) value ); + } + }; + break; + + case SQL_FLOAT: + sprintf ( p, "%15g ", *( float ISC_FAR * ) ( var->sqldata ) ); + break; + + case SQL_DOUBLE: + sprintf ( p, "%24f ", *( double ISC_FAR * ) ( var->sqldata ) ); + break; + + case SQL_TIMESTAMP: + isc_decode_timestamp ( ( ISC_TIMESTAMP ISC_FAR * ) var->sqldata, × ); + sprintf ( date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04lui", + times.tm_year + 1900, + times.tm_mon + 1, + times.tm_mday, + times.tm_hour, + times.tm_min, + times.tm_sec, + ( ( ISC_TIMESTAMP * ) var->sqldata )->timestamp_time % 10000 ); + sprintf ( p, "%*s ", 24, date_s ); + break; + + case SQL_TYPE_DATE: + isc_decode_sql_date ( ( ISC_DATE ISC_FAR * ) var->sqldata, × ); + sprintf ( date_s, "%04d-%02d-%02d", + times.tm_year + 1900, times.tm_mon + 1, times.tm_mday ); + sprintf ( p, "%*s ", 10, date_s ); + break; + + case SQL_TYPE_TIME: + isc_decode_sql_time ( ( ISC_TIME ISC_FAR * ) var->sqldata, × ); + sprintf ( date_s, "%02d:%02d:%02d.%04lui", + times.tm_hour, + times.tm_min, + times.tm_sec, ( *( ( ISC_TIME * ) var->sqldata ) ) % 10000 ); + sprintf ( p, "%*s ", 13, date_s ); + break; + + case SQL_BLOB: + case SQL_ARRAY: + /* Print the blob id on blobs or arrays */ + bid = *( ISC_QUAD ISC_FAR * ) var->sqldata; + sprintf ( blob_s, "%08x:%08x", ( unsigned int ) bid.gds_quad_high, + ( unsigned int ) bid.gds_quad_low ); + sprintf ( p, "%17s ", blob_s ); + break; + + default: + break; + } + } + + return ( p ); +} diff --git a/harbour/contrib/firebird/tfirebird.prg b/harbour/contrib/firebird/tfirebird.prg index 15ba12f7fa..caaba0547e 100644 --- a/harbour/contrib/firebird/tfirebird.prg +++ b/harbour/contrib/firebird/tfirebird.prg @@ -1,1063 +1,1063 @@ -/* - * $Id: atrepl.c 7583 2007-07-06 21:17:36Z druzus $ - */ - -/* - * xHarbour Project source code: - * Firebird RDBMS low level (client api) interface code. - * - * Copyright 2003 Rodrigo Moreno rodrigo_moreno@yahoo.com - * www - http://www.xharbour.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). - * - * As a special exception, the Harbour Project gives permission for - * additional uses of the text contained in its release of Harbour. - * - * The exception is that, if you link the Harbour libraries with other - * files to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the Harbour library code into it. - * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. - * - * This exception applies only to the code released by the Harbour - * Project under the name Harbour. If you copy code from other - * Harbour Project or Free Software Foundation releases into a copy of - * Harbour, as the General Public License permits, the exception does - * not apply to the code that you add in this way. To avoid misleading - * anyone as to the status of such modified files, you must delete - * this exception notice from them. - * - * If you write modifications of your own for Harbour, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. - * - * See doc/license.txt for licensing terms. - * - */ - -#include "common.ch" -#include "hbclass.ch" - -#define SQL_TEXT 452 -#define SQL_VARYING 448 -#define SQL_SHORT 500 -#define SQL_LONG 496 -#define SQL_FLOAT 482 -#define SQL_DOUBLE 480 -#define SQL_D_FLOAT 530 -#define SQL_TIMESTAMP 510 -#define SQL_BLOB 520 -#define SQL_ARRAY 540 -#define SQL_QUAD 550 -#define SQL_TYPE_TIME 560 -#define SQL_TYPE_DATE 570 -#define SQL_INT64 580 -#define SQL_DATE SQL_TIMESTAMP - - -CLASS TFbServer - DATA db - DATA trans - DATA StartedTrans - DATA nError - DATA lError - DATA dialect - - METHOD New( cServer, cUser, cPassword, nDialect ) - METHOD Destroy() INLINE FBClose(::db) - METHOD Close() INLINE FBClose(::db) - - METHOD TableExists( cTable ) - METHOD ListTables() - METHOD TableStruct( cTable ) - - METHOD StartTransaction() - METHOD Commit() - METHOD Rollback() - - METHOD Execute( cQuery ) - METHOD Query( cQuery ) - - METHOD Update( oRow, cWhere ) - METHOD Delete( oRow, cWhere ) - METHOD Append( oRow ) - - METHOD NetErr() INLINE ::lError - METHOD Error() INLINE FBError(::nError) - METHOD ErrorNo() INLINE ::nError -ENDCLASS - - -METHOD New( cServer, cUser, cPassword, nDialect ) CLASS TFbServer - - Default nDialect TO 1 - - ::lError := .F. - ::nError := 0 - ::StartedTrans := .F. - ::Dialect := nDialect - - ::db := FBConnect(cServer, cUser, cPassword) - - if ISNUMBER(::db) - ::lError := .T. - ::nError := ::db - end -RETURN self - - -METHOD StartTransaction() CLASS TFbServer - Local result := .F. - - ::trans := FBStartTransaction(::db) - - if ISNUMBER(::trans) - ::lError := .T. - ::nError := ::trans - else - result := .T. - ::lError := .F. - ::lnError := 0 - ::StartedTrans := .T. - end -RETURN result - - -METHOD Rollback() CLASS TFbServer - Local result := .F., n - - if ::StartedTrans - if (n := FBRollback(::trans)) < 0 - ::lError := .T. - ::nError := n - else - ::lError := .F. - ::nError := 0 - result := .T. - ::StartedTrans := .F. - end - end -RETURN result - - -METHOD Commit() CLASS TFbServer - Local result := .F., n - - if ::StartedTrans - if (n := FBCommit(::trans)) < 0 - ::lError := .T. - ::nError := n - else - ::lError := .F. - ::nError := 0 - result := .T. - ::StartedTrans := .F. - end - end -RETURN result - - -METHOD Execute( cQuery ) CLASS TFbServer - Local result, n - - cQuery := RemoveSpaces(cQuery) - - if ::StartedTrans - n := FBExecute( ::db, cQuery, ::dialect, ::trans ) - else - n := FBExecute( ::db, cQuery, ::dialect ) - end - - if n < 0 - ::lError := .T. - ::nError := n - result := .F. - else - ::lError := .F. - ::nError := 0 - result := .T. - end -RETURN result - - -METHOD Query( cQuery ) CLASS TFbServer - Local oQuery - - oQuery := TFbQuery():New(::db, cQuery, ::dialect) -RETURN oQuery - - -METHOD TableExists( cTable ) CLASS TFbServer - Local cQuery, result := .F., qry - - cQuery := 'select rdb$relation_name from rdb$relations where rdb$relation_name = "' + Upper(cTable) + '"' - - qry := FBQuery(::db, cQuery, ::dialect) - - if ISARRAY(qry) - result := (FBFetch(qry) == 0) - - FBFree(qry) - end - -RETURN result - - -METHOD ListTables() CLASS TFbServer - Local result := {}, cQuery, qry, fetch_stmt - - cQuery := 'select rdb$relation_name ' - cQuery += ' from rdb$relations ' - cQuery += ' where rdb$relation_name not like "RDB$%" ' - cQuery += ' and rdb$view_blr is null ' - cQuery += ' order by 1 ' - - qry := FBQuery(::db, RemoveSpaces(cQuery), ::dialect) - - if ISARRAY(qry) - do while (fetch_stmt := FBFetch(qry)) == 0 - aadd( result, FBGetdata(qry, 1) ) - end - - FBFree(qry) - end -RETURN result - - -METHOD TableStruct( cTable ) CLASS TFbServer - Local result := {}, cQuery, cType, nSize, cDomain, cField, nType, nDec, fetch_stmt - Local qry - - - cQuery := 'select ' - cQuery += ' a.rdb$field_name,' - cQuery += ' b.rdb$field_type,' - cQuery += ' b.rdb$field_length,' - cQuery += ' b.rdb$field_scale * -1,' - cQuery += ' a.rdb$field_source ' - cQuery += 'from ' - cQuery += ' rdb$relation_fields a, rdb$fields b ' - cQuery += 'where ' - cQuery += ' a.rdb$field_source = b.rdb$field_name ' - cQuery += ' and a.rdb$relation_name = "' + Upper(ctable) + '" ' - cQuery += 'order by ' - cQuery += ' a.rdb$field_position ' - - qry := FBQuery(::db, RemoveSpaces(cQuery), ::dialect) - - if ISARRAY(qry) - do while (fetch_stmt := FBFetch(qry)) == 0 - cField := FBGetData(qry, 1) - nType := val(FBGetData(qry, 2)) - nSize := val(FBGetData(qry, 3)) - nDec := val(FBGetData(qry, 4)) - cDomain := FBGetData(qry, 5) - - switch nType - case 7 // SMALLINT - if "BOOL" $ cDomain - cType := "L" - nSize := 1 - nDec := 0 - else - cType := 'N' - nSize := 5 - end - - exit - - case 8 // INTEGER - case 9 - cType := 'N' - nSize := 9 - exit - - case 10 // FLOAT - case 11 - cType := 'N' - nSize := 15 - exit - - case 12 // DATE - cType := 'D' - nSize := 8 - exit - - case 13 // TIME - cType := 'C' - nSize := 10 - exit - - case 14 // CHAR - cType := 'C' - exit - - case 16 // INT64 - cType := 'N' - nSize := 9 - exit - - case 27 // DOUBLE - cType := 'N' - nSize := 15 - exit - - case 35 // TIMESTAMP - cType := 'D' - nSize := 8 - exit - - case 37 // VARCHAR - case 40 - cType := 'C' - exit - - case 261 // BLOB - cType := 'M' - nSize := 10 - exit - - otherwise - cType := 'C' - nDec := 0 - end - - aadd( result, { cField, cType, nSize, nDec } ) - - end - - FBFree(qry) - end -RETURN result - - -METHOD Delete( oRow, cWhere ) CLASS TFbServer - Local result := .F., aKeys, i, nField, xField, cQuery, aTables - - aTables := oRow:GetTables() - - if ! ISNUMBER(::db) .and. len(aTables) == 1 - // Cannot delete joined tables - - if ISNIL(cWhere) - aKeys := oRow:GetKeyField() - - cWhere := '' - For i := 1 to len(aKeys) - nField := oRow:Fieldpos(aKeys[i]) - xField := oRow:Fieldget(nField) - - cWhere += aKeys[i] + '=' + DataToSql(xField) - - if i <> len(aKeys) - cWhere += ',' - end - Next - end - - if ! (cWhere == '') - cQuery := 'DELETE FROM ' + aTables[1] + ' WHERE ' + cWhere - - result := ::Execute(cQuery) - end - end -RETURN result - - -METHOD Append( oRow ) CLASS TFbServer - Local result := .F., cQuery, i, aTables - - aTables := oRow:GetTables() - - if ! ISNUMBER(::db) .and. len(aTables) == 1 - // Can insert only one table, not in joined tables - - cQuery := 'INSERT INTO ' + aTables[1] + '(' - For i := 1 to oRow:FCount() - if oRow:Changed(i) - // Send only changed field - cQuery += oRow:Fieldname(i) + ',' - end - Next - - cQuery := Left( cQuery, len(cQuery) - 1 ) + ') VALUES (' - - For i := 1 to oRow:FCount() - if oRow:Changed(i) - cQuery += DataToSql(oRow:FieldGet(i)) + ',' - end - Next - - cQuery := Left( cQuery, len(cQuery) - 1 ) + ')' - - result := ::Execute(cQuery) - end -RETURN result - - -METHOD Update( oRow, cWhere ) CLASS TFbServer - Local result := .F., aKeys, cQuery, i, nField, xField, aTables - - aTables := oRow:GetTables() - - if ! ISNUMBER(::db) .and. len(aTables) == 1 - // Can't insert joined tables - - if ISNIL(cWhere) - aKeys := oRow:GetKeyField() - - cWhere := '' - For i := 1 to len(aKeys) - nField := oRow:Fieldpos(aKeys[i]) - xField := oRow:Fieldget(nField) - - cWhere += aKeys[i] + '=' + DataToSql(xField) - - if i <> len(aKeys) - cWhere += ', ' - end - Next - end - - cQuery := 'UPDATE ' + aTables[1] + ' SET ' - For i := 1 to oRow:FCount() - if oRow:Changed(i) - cQuery += oRow:Fieldname(i) + ' = ' + DataToSql(oRow:FieldGet(i)) + ',' - end - Next - - if ! (cWhere == '') - cQuery := Left( cQuery, len(cQuery) - 1 ) + ' WHERE ' + cWhere - - result := ::Execute(cQuery) - end - end -RETURN result - - -CLASS TFbQuery - DATA ErrorNo - DATA nError - DATA lError - DATA Dialect - DATA lBof - DATA lEof - DATA nRecno - DATA qry - DATA aStruct - DATA numcols - DATA closed - DATA db - DATA query - DATA aKeys - DATA aTables - - METHOD New( db, cQuery, nDialect ) - METHOD Destroy() - METHOD Close() INLINE ::Destroy() - - METHOD Refresh() - METHOD Fetch() - METHOD Skip() INLINE ::Fetch() - - METHOD Bof() INLINE ::lBof - METHOD Eof() INLINE ::lEof - METHOD RecNo() INLINE ::nRecno - - METHOD NetErr() INLINE ::lError - METHOD Error() INLINE FBError(::nError) - METHOD ErrorNo() INLINE ::nError - - METHOD FCount() INLINE ::numcols - METHOD Struct() - METHOD FieldName( nField ) - METHOD FieldPos( cField ) - METHOD FieldLen( nField ) - METHOD FieldDec( nField ) - METHOD FieldType( nField ) - - METHOD FieldGet( nField ) - METHOD GetRow() - METHOD GetBlankRow() - METHOD Blank() INLINE ::GetBlankRow() - METHOD GetKeyField() - -ENDCLASS - - -METHOD New( nDB, cQuery, nDialect ) CLASS TFbQuery - ::db := nDb - ::query := RemoveSpaces(cQuery) - ::dialect := nDialect - ::closed := .T. - ::aKeys := NIL - - ::Refresh() - -RETURN self - - -METHOD Refresh() CLASS TFbQuery - Local qry, result := .F., i, aTable := {} - - if ! ::closed - ::Destroy() - end - - ::lBof := .T. - ::lEof := .F. - ::nRecno := 0 - ::closed := .F. - ::numcols := 0 - ::aStruct := {} - ::nError := 0 - ::lError := .F. - - result := .T. - - qry := FBQuery( ::db, ::query, ::dialect ) - - if ISARRAY(qry) - ::numcols := qry[4] - - ::aStruct := StructConvert(qry[6], ::db, ::dialect) - - ::lError := .F. - ::nError := 0 - ::qry := qry - - /* Tables in query */ - For i := 1 To len(::aStruct) - if (ASCAN(aTable, ::aStruct[i,5]) == 0) - aadd( aTable, ::aStruct[i,5]) - end - Next - - ::aTables := aTable - - else - ::lError := .T. - ::nError := qry - end - -RETURN result - - -METHOD Destroy() CLASS TFbQuery - Local result := .T., n - - if (! ::lError) .and. ((n := FBFree(::qry)) < 0) - ::lError := .T. - ::nError := n - end - - ::closed := .T. - -RETURN result - - -METHOD Fetch() CLASS TFbQuery - Local result := .F., fetch_stat - - if ! ::lError .and. ! ::lEof - - if ! ::Closed - fetch_stat := FBFetch(::qry) - - ::nRecno++ - - if fetch_stat == 0 - ::lBof := .F. - result := .T. - - else - ::lEof := .T. - - end - end - end -RETURN result - - -METHOD Struct() CLASS TFbQuery - Local result := {}, i - - if ! ::lError - for i := 1 to Len(::aStruct) - aadd( result, { ::aStruct[i,1], ::aStruct[i,2], ::aStruct[i,3], ::aStruct[i,4] } ) - next - end - -RETURN result - - -METHOD FieldPos( cField ) CLASS TFbQuery - Local result := 0 - - if ! ::lError - result := AScan( ::aStruct, {|x| x[1] == trim(Upper(cField)) }) - end - -RETURN result - - -METHOD FieldName( nField ) CLASS TFbQuery - Local result - - if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 1] - end - -RETURN result - - -METHOD FieldType( nField ) CLASS TFbQuery - Local result - - if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 2] - end - -RETURN result - - -METHOD FieldLen( nField ) CLASS TFbQuery - Local result - - if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 3] - end -RETURN result - - -METHOD FieldDec( nField ) CLASS TFbQuery - Local result - - if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 4] - end -RETURN result - - -METHOD FieldGet( nField ) CLASS TFbQuery - Local result, aBlob, i, cType - - if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) .and. ! ::closed - - /* TODO: Convert to right data type */ - - result := FBGetData(::qry, nField) - cType := ::aStruct[ nField, 2 ] - - if cType == "M" - /* Blob */ - - if ! ISNIL(result) - aBlob := FBGetBlob( ::db, result) - - result := '' - For i := 1 to Len(aBlob) - result += aBlob[i] - Next - - //result := FBGetBlob( ::db, result) - else - result := '' - end - - elseif cType == "N" - if ! ISNIL(result) - result := val(result) - else - result := 0 - end - - elseif cType == "D" - if ! ISNIL(result) - result := StoD(left(result,4) + substr(result, 5, 2) + substr(result, 7, 2)) - else - result := CtoD('') - end - - elseif cType == "L" - if ! ISNIL(result) - result := (val(result) == 1) - else - result := .F. - end - end - end -RETURN result - - -METHOD Getrow() CLASS TFbQuery - Local result, aRow := {}, i - - if ! ::lError .and. ! ::closed - ASize(aRow, ::numcols) - - For i := 1 to ::numcols - aRow[i] := ::Fieldget(i) - Next - - result := TFbRow():New( aRow, ::aStruct, ::db, ::dialect, ::aTables ) - end -RETURN result - - -METHOD GetBlankRow() CLASS TFbQuery - Local result, aRow := {}, i - - if ! ::lError - ASize(aRow, ::numcols) - - For i := 1 to ::numcols - if ::aStruct[i, 2] == 'C' - aRow[i] := '' - elseif ::aStruct[i, 2] == 'N' - aRow[i] := 0 - elseif ::aStruct[i, 2] == 'L' - aRow[i] := .F. - elseif ::aStruct[i, 2] == 'D' - aRow[i] := CtoD('') - elseif ::aStruct[i, 2] == 'M' - aRow[i] := '' - end - Next - - result := TFbRow():New( aRow, ::aStruct, ::db, ::dialect, ::aTables ) - end -RETURN result - - -METHOD GetKeyField() CLASS TFbQuery - - if ISNIL(::aKeys) - ::aKeys := KeyField( ::aTables, ::db, ::dialect ) - end -RETURN ::aKeys - - -CLASS TFbRow - DATA aRow - DATA aStruct - DATA aChanged - DATA aKeys - DATA db - DATA dialect - DATA aTables - - METHOD New( row, struct, db, dialect ) - METHOD Changed(nField) - METHOD GetTables() INLINE ::aTables - METHOD FCount() INLINE Len(::aRow) - METHOD FieldGet( nField ) - METHOD FieldPut( nField, Value ) - METHOD FieldName( nField ) - METHOD FieldPos( cFieldName ) - METHOD FieldLen( nField ) - METHOD FieldDec( nField ) - METHOD FieldType( nField ) - METHOD GetKeyField() -ENDCLASS - - -METHOD new( row, struct, nDb, nDialect, aTable ) CLASS TFbRow - ::aRow := row - ::aStruct := struct - ::db := nDB - ::dialect := nDialect - ::aTables := aTable - ::aChanged := Array(len(row)) -RETURN self - - -METHOD Changed( nField ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aRow) - result := ! ISNIL(::aChanged[nField]) - end - -RETURN result - - -METHOD FieldGet( nField ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aRow) - result := ::aRow[nField] - end - -RETURN result - - -METHOD FieldPut( nField, Value ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aRow) - ::aChanged[nField] := .T. - result := ::aRow[nField] := Value - end - -RETURN result - - -METHOD FieldName( nField ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 1] - end - -RETURN result - - -METHOD FieldPos( cField ) CLASS TFbRow - Local result := 0 - - result := AScan( ::aStruct, {|x| x[1] == trim(Upper(cField)) }) - -RETURN result - - -METHOD FieldType( nField ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 2] - end - -RETURN result - - -METHOD FieldLen( nField ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 3] - end -RETURN result - - -METHOD FieldDec( nField ) CLASS TFbRow - Local result - - if nField >= 1 .and. nField <= len(::aStruct) - result := ::aStruct[nField, 4] - end -RETURN result - - -METHOD GetKeyField() CLASS TFbRow - - if ISNIL(::aKeys) - ::aKeys := KeyField( ::aTables, ::db, ::dialect ) - end -RETURN ::aKeys - - - -Static Function KeyField( aTables, db, dialect ) - Local cTable, cQuery - Local qry, fetch_stmt - Local aKeys := {} - - /* Check row, many tables exists in current query, so we must have only one table */ - - if Len(aTables) = 1 - cTable := aTables[1] - - cQuery := ' select ' - cQuery += ' a.rdb$field_name ' - cQuery += ' from ' - cQuery += ' rdb$index_segments a, ' - cQuery += ' rdb$relation_constraints b ' - cQuery += ' where ' - cQuery += ' a.rdb$index_name = b.rdb$index_name and ' - cQuery += ' b.rdb$constraint_type = "PRIMARY KEY" and ' - cQuery += ' b.rdb$relation_name = ' + DataToSql(cTable) - cQuery += ' order by ' - cQuery += ' b.rdb$relation_name, ' - cQuery += ' a.rdb$field_position ' - - qry := FBQuery(db, RemoveSpaces(cQuery), dialect) - - if ISARRAY(qry) - do while (fetch_stmt := FBFetch(qry)) == 0 - aadd(aKeys, trim(FBGetdata(qry, 1))) - end - - FBFree(qry) - end - end - -RETURN aKeys - - -Static Function DataToSql(xField) - Local cType, result - - cType := ValType(xField) - - if cType == "C" - result := '"' + strtran(xField, '"', ' ') + '"' - elseif cType == "D" - result := '"' + StrZero(month(xField),2) + '/' + StrZero(day(xField),2) + '/' + StrZero(Year(xField),4) + '"' - elseif cType == "N" - result := str(xField) - elseif cType == "L" - result := iif( xField, '1', '0' ) - end - -return result - - -Static Function StructConvert( aStru, db, dialect) - Local aNew := {} - Local cField - Local nType - Local cType - Local nSize - Local nDec - Local cTable - Local cDomain - Local i - Local qry - Local cQuery - Local aDomains := {} - Local fetch_stmt - Local nVal - - Local xTables := '' - Local xFields := '' - - /* create table list and field list */ - - For i := 1 to Len(aStru) - xtables += DataToSql(aStru[i, 5]) - xfields += DataToSql(aStru[i, 1]) - - if i <> len(aStru) - xtables += ',' - xfields += ',' - end - Next - - /* Look for domains */ - cQuery := 'select rdb$relation_name, rdb$field_name, rdb$field_source ' - cQuery += ' from rdb$relation_fields ' - cQuery += ' where rdb$field_name not like "RDB$%" ' - cQuery += ' and rdb$relation_name in (' + xtables + ')' - cQuery += ' and rdb$field_name in (' + xfields + ')' - - qry := FBQuery(db, RemoveSpaces(cQuery), dialect) - - if ISARRAY(qry) - - do while (fetch_stmt := FBFetch(qry)) == 0 - aadd( aDomains, { FBGetdata(qry, 1), FBGetdata(qry,2), FBGetdata(qry,3) } ) - end - - FBFree(qry) - - For i := 1 to Len(aStru) - cField := trim(aStru[i,1]) - nType := aStru[i,2] - nSize := aStru[i,3] - nDec := aStru[i,4] * -1 - cTable := trim(aStru[i,5]) - - nVal := AScan(aDomains, {|x| trim(x[1]) == cTable .and. trim(x[2]) == cField}) - - if nVal != 0 - cDomain := aDomains[ nVal, 3 ] - else - cDomain := '' - end - - switch nType - case SQL_TEXT - cType := "C" - exit - case SQL_VARYING - cType := "C" - exit - case SQL_SHORT - /* Firebird doesn't have boolean field, so if you define domain with BOOL then i will consider logical, ex: - create domain boolean_field as smallint default 0 not null check (value in (0,1)) */ - - if "BOOL" $ cDomain - cType := "L" - nSize := 1 - nDec := 0 - else - cType := "N" - nSize := 5 - end - exit - case SQL_LONG - cType := "N" - nSize := 9 - exit - case SQL_INT64 - cType := "N" - nSize := 9 - exit - case SQL_FLOAT - cType := "N" - nSize := 15 - exit - case SQL_DOUBLE - cType := "N" - nSize := 15 - exit - case SQL_TIMESTAMP - cType := "D" - nSize := 8 - exit - case SQL_TYPE_DATE - cType := "D" - nSize := 8 - exit - case SQL_TYPE_TIME - cType := "C" - nSize := 8 - exit - case SQL_BLOB - cType := "M" - nSize := 10 - exit - otherwise - cType := "C" - nDec := 0 - end - - aadd( aNew, { cField, cType, nSize, nDec, cTable, cDomain } ) - Next - End - -return aNew - -Static Function RemoveSpaces( cQuery ) - Do While AT(" ", cQuery) != 0 - cQuery := Strtran(cQuery, " ", " ") - end -Return cQuery +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * Firebird RDBMS low level (client api) interface code. + * + * Copyright 2003 Rodrigo Moreno rodrigo_moreno@yahoo.com + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + * See doc/license.txt for licensing terms. + * + */ + +#include "common.ch" +#include "hbclass.ch" + +#define SQL_TEXT 452 +#define SQL_VARYING 448 +#define SQL_SHORT 500 +#define SQL_LONG 496 +#define SQL_FLOAT 482 +#define SQL_DOUBLE 480 +#define SQL_D_FLOAT 530 +#define SQL_TIMESTAMP 510 +#define SQL_BLOB 520 +#define SQL_ARRAY 540 +#define SQL_QUAD 550 +#define SQL_TYPE_TIME 560 +#define SQL_TYPE_DATE 570 +#define SQL_INT64 580 +#define SQL_DATE SQL_TIMESTAMP + + +CLASS TFbServer + DATA db + DATA trans + DATA StartedTrans + DATA nError + DATA lError + DATA dialect + + METHOD New( cServer, cUser, cPassword, nDialect ) + METHOD Destroy() INLINE FBClose(::db) + METHOD Close() INLINE FBClose(::db) + + METHOD TableExists( cTable ) + METHOD ListTables() + METHOD TableStruct( cTable ) + + METHOD StartTransaction() + METHOD Commit() + METHOD Rollback() + + METHOD Execute( cQuery ) + METHOD Query( cQuery ) + + METHOD Update( oRow, cWhere ) + METHOD Delete( oRow, cWhere ) + METHOD Append( oRow ) + + METHOD NetErr() INLINE ::lError + METHOD Error() INLINE FBError(::nError) + METHOD ErrorNo() INLINE ::nError +ENDCLASS + + +METHOD New( cServer, cUser, cPassword, nDialect ) CLASS TFbServer + + Default nDialect TO 1 + + ::lError := .F. + ::nError := 0 + ::StartedTrans := .F. + ::Dialect := nDialect + + ::db := FBConnect(cServer, cUser, cPassword) + + if ISNUMBER(::db) + ::lError := .T. + ::nError := ::db + end +RETURN self + + +METHOD StartTransaction() CLASS TFbServer + Local result := .F. + + ::trans := FBStartTransaction(::db) + + if ISNUMBER(::trans) + ::lError := .T. + ::nError := ::trans + else + result := .T. + ::lError := .F. + ::lnError := 0 + ::StartedTrans := .T. + end +RETURN result + + +METHOD Rollback() CLASS TFbServer + Local result := .F., n + + if ::StartedTrans + if (n := FBRollback(::trans)) < 0 + ::lError := .T. + ::nError := n + else + ::lError := .F. + ::nError := 0 + result := .T. + ::StartedTrans := .F. + end + end +RETURN result + + +METHOD Commit() CLASS TFbServer + Local result := .F., n + + if ::StartedTrans + if (n := FBCommit(::trans)) < 0 + ::lError := .T. + ::nError := n + else + ::lError := .F. + ::nError := 0 + result := .T. + ::StartedTrans := .F. + end + end +RETURN result + + +METHOD Execute( cQuery ) CLASS TFbServer + Local result, n + + cQuery := RemoveSpaces(cQuery) + + if ::StartedTrans + n := FBExecute( ::db, cQuery, ::dialect, ::trans ) + else + n := FBExecute( ::db, cQuery, ::dialect ) + end + + if n < 0 + ::lError := .T. + ::nError := n + result := .F. + else + ::lError := .F. + ::nError := 0 + result := .T. + end +RETURN result + + +METHOD Query( cQuery ) CLASS TFbServer + Local oQuery + + oQuery := TFbQuery():New(::db, cQuery, ::dialect) +RETURN oQuery + + +METHOD TableExists( cTable ) CLASS TFbServer + Local cQuery, result := .F., qry + + cQuery := 'select rdb$relation_name from rdb$relations where rdb$relation_name = "' + Upper(cTable) + '"' + + qry := FBQuery(::db, cQuery, ::dialect) + + if ISARRAY(qry) + result := (FBFetch(qry) == 0) + + FBFree(qry) + end + +RETURN result + + +METHOD ListTables() CLASS TFbServer + Local result := {}, cQuery, qry, fetch_stmt + + cQuery := 'select rdb$relation_name ' + cQuery += ' from rdb$relations ' + cQuery += ' where rdb$relation_name not like "RDB$%" ' + cQuery += ' and rdb$view_blr is null ' + cQuery += ' order by 1 ' + + qry := FBQuery(::db, RemoveSpaces(cQuery), ::dialect) + + if ISARRAY(qry) + do while (fetch_stmt := FBFetch(qry)) == 0 + aadd( result, FBGetdata(qry, 1) ) + end + + FBFree(qry) + end +RETURN result + + +METHOD TableStruct( cTable ) CLASS TFbServer + Local result := {}, cQuery, cType, nSize, cDomain, cField, nType, nDec, fetch_stmt + Local qry + + + cQuery := 'select ' + cQuery += ' a.rdb$field_name,' + cQuery += ' b.rdb$field_type,' + cQuery += ' b.rdb$field_length,' + cQuery += ' b.rdb$field_scale * -1,' + cQuery += ' a.rdb$field_source ' + cQuery += 'from ' + cQuery += ' rdb$relation_fields a, rdb$fields b ' + cQuery += 'where ' + cQuery += ' a.rdb$field_source = b.rdb$field_name ' + cQuery += ' and a.rdb$relation_name = "' + Upper(ctable) + '" ' + cQuery += 'order by ' + cQuery += ' a.rdb$field_position ' + + qry := FBQuery(::db, RemoveSpaces(cQuery), ::dialect) + + if ISARRAY(qry) + do while (fetch_stmt := FBFetch(qry)) == 0 + cField := FBGetData(qry, 1) + nType := val(FBGetData(qry, 2)) + nSize := val(FBGetData(qry, 3)) + nDec := val(FBGetData(qry, 4)) + cDomain := FBGetData(qry, 5) + + switch nType + case 7 // SMALLINT + if "BOOL" $ cDomain + cType := "L" + nSize := 1 + nDec := 0 + else + cType := 'N' + nSize := 5 + end + + exit + + case 8 // INTEGER + case 9 + cType := 'N' + nSize := 9 + exit + + case 10 // FLOAT + case 11 + cType := 'N' + nSize := 15 + exit + + case 12 // DATE + cType := 'D' + nSize := 8 + exit + + case 13 // TIME + cType := 'C' + nSize := 10 + exit + + case 14 // CHAR + cType := 'C' + exit + + case 16 // INT64 + cType := 'N' + nSize := 9 + exit + + case 27 // DOUBLE + cType := 'N' + nSize := 15 + exit + + case 35 // TIMESTAMP + cType := 'D' + nSize := 8 + exit + + case 37 // VARCHAR + case 40 + cType := 'C' + exit + + case 261 // BLOB + cType := 'M' + nSize := 10 + exit + + otherwise + cType := 'C' + nDec := 0 + end + + aadd( result, { cField, cType, nSize, nDec } ) + + end + + FBFree(qry) + end +RETURN result + + +METHOD Delete( oRow, cWhere ) CLASS TFbServer + Local result := .F., aKeys, i, nField, xField, cQuery, aTables + + aTables := oRow:GetTables() + + if ! ISNUMBER(::db) .and. len(aTables) == 1 + // Cannot delete joined tables + + if ISNIL(cWhere) + aKeys := oRow:GetKeyField() + + cWhere := '' + For i := 1 to len(aKeys) + nField := oRow:Fieldpos(aKeys[i]) + xField := oRow:Fieldget(nField) + + cWhere += aKeys[i] + '=' + DataToSql(xField) + + if i <> len(aKeys) + cWhere += ',' + end + Next + end + + if ! (cWhere == '') + cQuery := 'DELETE FROM ' + aTables[1] + ' WHERE ' + cWhere + + result := ::Execute(cQuery) + end + end +RETURN result + + +METHOD Append( oRow ) CLASS TFbServer + Local result := .F., cQuery, i, aTables + + aTables := oRow:GetTables() + + if ! ISNUMBER(::db) .and. len(aTables) == 1 + // Can insert only one table, not in joined tables + + cQuery := 'INSERT INTO ' + aTables[1] + '(' + For i := 1 to oRow:FCount() + if oRow:Changed(i) + // Send only changed field + cQuery += oRow:Fieldname(i) + ',' + end + Next + + cQuery := Left( cQuery, len(cQuery) - 1 ) + ') VALUES (' + + For i := 1 to oRow:FCount() + if oRow:Changed(i) + cQuery += DataToSql(oRow:FieldGet(i)) + ',' + end + Next + + cQuery := Left( cQuery, len(cQuery) - 1 ) + ')' + + result := ::Execute(cQuery) + end +RETURN result + + +METHOD Update( oRow, cWhere ) CLASS TFbServer + Local result := .F., aKeys, cQuery, i, nField, xField, aTables + + aTables := oRow:GetTables() + + if ! ISNUMBER(::db) .and. len(aTables) == 1 + // Can't insert joined tables + + if ISNIL(cWhere) + aKeys := oRow:GetKeyField() + + cWhere := '' + For i := 1 to len(aKeys) + nField := oRow:Fieldpos(aKeys[i]) + xField := oRow:Fieldget(nField) + + cWhere += aKeys[i] + '=' + DataToSql(xField) + + if i <> len(aKeys) + cWhere += ', ' + end + Next + end + + cQuery := 'UPDATE ' + aTables[1] + ' SET ' + For i := 1 to oRow:FCount() + if oRow:Changed(i) + cQuery += oRow:Fieldname(i) + ' = ' + DataToSql(oRow:FieldGet(i)) + ',' + end + Next + + if ! (cWhere == '') + cQuery := Left( cQuery, len(cQuery) - 1 ) + ' WHERE ' + cWhere + + result := ::Execute(cQuery) + end + end +RETURN result + + +CLASS TFbQuery + DATA ErrorNo + DATA nError + DATA lError + DATA Dialect + DATA lBof + DATA lEof + DATA nRecno + DATA qry + DATA aStruct + DATA numcols + DATA closed + DATA db + DATA query + DATA aKeys + DATA aTables + + METHOD New( db, cQuery, nDialect ) + METHOD Destroy() + METHOD Close() INLINE ::Destroy() + + METHOD Refresh() + METHOD Fetch() + METHOD Skip() INLINE ::Fetch() + + METHOD Bof() INLINE ::lBof + METHOD Eof() INLINE ::lEof + METHOD RecNo() INLINE ::nRecno + + METHOD NetErr() INLINE ::lError + METHOD Error() INLINE FBError(::nError) + METHOD ErrorNo() INLINE ::nError + + METHOD FCount() INLINE ::numcols + METHOD Struct() + METHOD FieldName( nField ) + METHOD FieldPos( cField ) + METHOD FieldLen( nField ) + METHOD FieldDec( nField ) + METHOD FieldType( nField ) + + METHOD FieldGet( nField ) + METHOD GetRow() + METHOD GetBlankRow() + METHOD Blank() INLINE ::GetBlankRow() + METHOD GetKeyField() + +ENDCLASS + + +METHOD New( nDB, cQuery, nDialect ) CLASS TFbQuery + ::db := nDb + ::query := RemoveSpaces(cQuery) + ::dialect := nDialect + ::closed := .T. + ::aKeys := NIL + + ::Refresh() + +RETURN self + + +METHOD Refresh() CLASS TFbQuery + Local qry, result := .F., i, aTable := {} + + if ! ::closed + ::Destroy() + end + + ::lBof := .T. + ::lEof := .F. + ::nRecno := 0 + ::closed := .F. + ::numcols := 0 + ::aStruct := {} + ::nError := 0 + ::lError := .F. + + result := .T. + + qry := FBQuery( ::db, ::query, ::dialect ) + + if ISARRAY(qry) + ::numcols := qry[4] + + ::aStruct := StructConvert(qry[6], ::db, ::dialect) + + ::lError := .F. + ::nError := 0 + ::qry := qry + + /* Tables in query */ + For i := 1 To len(::aStruct) + if (ASCAN(aTable, ::aStruct[i,5]) == 0) + aadd( aTable, ::aStruct[i,5]) + end + Next + + ::aTables := aTable + + else + ::lError := .T. + ::nError := qry + end + +RETURN result + + +METHOD Destroy() CLASS TFbQuery + Local result := .T., n + + if (! ::lError) .and. ((n := FBFree(::qry)) < 0) + ::lError := .T. + ::nError := n + end + + ::closed := .T. + +RETURN result + + +METHOD Fetch() CLASS TFbQuery + Local result := .F., fetch_stat + + if ! ::lError .and. ! ::lEof + + if ! ::Closed + fetch_stat := FBFetch(::qry) + + ::nRecno++ + + if fetch_stat == 0 + ::lBof := .F. + result := .T. + + else + ::lEof := .T. + + end + end + end +RETURN result + + +METHOD Struct() CLASS TFbQuery + Local result := {}, i + + if ! ::lError + for i := 1 to Len(::aStruct) + aadd( result, { ::aStruct[i,1], ::aStruct[i,2], ::aStruct[i,3], ::aStruct[i,4] } ) + next + end + +RETURN result + + +METHOD FieldPos( cField ) CLASS TFbQuery + Local result := 0 + + if ! ::lError + result := AScan( ::aStruct, {|x| x[1] == trim(Upper(cField)) }) + end + +RETURN result + + +METHOD FieldName( nField ) CLASS TFbQuery + Local result + + if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 1] + end + +RETURN result + + +METHOD FieldType( nField ) CLASS TFbQuery + Local result + + if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 2] + end + +RETURN result + + +METHOD FieldLen( nField ) CLASS TFbQuery + Local result + + if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 3] + end +RETURN result + + +METHOD FieldDec( nField ) CLASS TFbQuery + Local result + + if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 4] + end +RETURN result + + +METHOD FieldGet( nField ) CLASS TFbQuery + Local result, aBlob, i, cType + + if ! ::lError .and. nField >= 1 .and. nField <= len(::aStruct) .and. ! ::closed + + /* TODO: Convert to right data type */ + + result := FBGetData(::qry, nField) + cType := ::aStruct[ nField, 2 ] + + if cType == "M" + /* Blob */ + + if ! ISNIL(result) + aBlob := FBGetBlob( ::db, result) + + result := '' + For i := 1 to Len(aBlob) + result += aBlob[i] + Next + + //result := FBGetBlob( ::db, result) + else + result := '' + end + + elseif cType == "N" + if ! ISNIL(result) + result := val(result) + else + result := 0 + end + + elseif cType == "D" + if ! ISNIL(result) + result := StoD(left(result,4) + substr(result, 5, 2) + substr(result, 7, 2)) + else + result := CtoD('') + end + + elseif cType == "L" + if ! ISNIL(result) + result := (val(result) == 1) + else + result := .F. + end + end + end +RETURN result + + +METHOD Getrow() CLASS TFbQuery + Local result, aRow := {}, i + + if ! ::lError .and. ! ::closed + ASize(aRow, ::numcols) + + For i := 1 to ::numcols + aRow[i] := ::Fieldget(i) + Next + + result := TFbRow():New( aRow, ::aStruct, ::db, ::dialect, ::aTables ) + end +RETURN result + + +METHOD GetBlankRow() CLASS TFbQuery + Local result, aRow := {}, i + + if ! ::lError + ASize(aRow, ::numcols) + + For i := 1 to ::numcols + if ::aStruct[i, 2] == 'C' + aRow[i] := '' + elseif ::aStruct[i, 2] == 'N' + aRow[i] := 0 + elseif ::aStruct[i, 2] == 'L' + aRow[i] := .F. + elseif ::aStruct[i, 2] == 'D' + aRow[i] := CtoD('') + elseif ::aStruct[i, 2] == 'M' + aRow[i] := '' + end + Next + + result := TFbRow():New( aRow, ::aStruct, ::db, ::dialect, ::aTables ) + end +RETURN result + + +METHOD GetKeyField() CLASS TFbQuery + + if ISNIL(::aKeys) + ::aKeys := KeyField( ::aTables, ::db, ::dialect ) + end +RETURN ::aKeys + + +CLASS TFbRow + DATA aRow + DATA aStruct + DATA aChanged + DATA aKeys + DATA db + DATA dialect + DATA aTables + + METHOD New( row, struct, db, dialect ) + METHOD Changed(nField) + METHOD GetTables() INLINE ::aTables + METHOD FCount() INLINE Len(::aRow) + METHOD FieldGet( nField ) + METHOD FieldPut( nField, Value ) + METHOD FieldName( nField ) + METHOD FieldPos( cFieldName ) + METHOD FieldLen( nField ) + METHOD FieldDec( nField ) + METHOD FieldType( nField ) + METHOD GetKeyField() +ENDCLASS + + +METHOD new( row, struct, nDb, nDialect, aTable ) CLASS TFbRow + ::aRow := row + ::aStruct := struct + ::db := nDB + ::dialect := nDialect + ::aTables := aTable + ::aChanged := Array(len(row)) +RETURN self + + +METHOD Changed( nField ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aRow) + result := ! ISNIL(::aChanged[nField]) + end + +RETURN result + + +METHOD FieldGet( nField ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aRow) + result := ::aRow[nField] + end + +RETURN result + + +METHOD FieldPut( nField, Value ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aRow) + ::aChanged[nField] := .T. + result := ::aRow[nField] := Value + end + +RETURN result + + +METHOD FieldName( nField ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 1] + end + +RETURN result + + +METHOD FieldPos( cField ) CLASS TFbRow + Local result := 0 + + result := AScan( ::aStruct, {|x| x[1] == trim(Upper(cField)) }) + +RETURN result + + +METHOD FieldType( nField ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 2] + end + +RETURN result + + +METHOD FieldLen( nField ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 3] + end +RETURN result + + +METHOD FieldDec( nField ) CLASS TFbRow + Local result + + if nField >= 1 .and. nField <= len(::aStruct) + result := ::aStruct[nField, 4] + end +RETURN result + + +METHOD GetKeyField() CLASS TFbRow + + if ISNIL(::aKeys) + ::aKeys := KeyField( ::aTables, ::db, ::dialect ) + end +RETURN ::aKeys + + + +Static Function KeyField( aTables, db, dialect ) + Local cTable, cQuery + Local qry, fetch_stmt + Local aKeys := {} + + /* Check row, many tables exists in current query, so we must have only one table */ + + if Len(aTables) = 1 + cTable := aTables[1] + + cQuery := ' select ' + cQuery += ' a.rdb$field_name ' + cQuery += ' from ' + cQuery += ' rdb$index_segments a, ' + cQuery += ' rdb$relation_constraints b ' + cQuery += ' where ' + cQuery += ' a.rdb$index_name = b.rdb$index_name and ' + cQuery += ' b.rdb$constraint_type = "PRIMARY KEY" and ' + cQuery += ' b.rdb$relation_name = ' + DataToSql(cTable) + cQuery += ' order by ' + cQuery += ' b.rdb$relation_name, ' + cQuery += ' a.rdb$field_position ' + + qry := FBQuery(db, RemoveSpaces(cQuery), dialect) + + if ISARRAY(qry) + do while (fetch_stmt := FBFetch(qry)) == 0 + aadd(aKeys, trim(FBGetdata(qry, 1))) + end + + FBFree(qry) + end + end + +RETURN aKeys + + +Static Function DataToSql(xField) + Local cType, result + + cType := ValType(xField) + + if cType == "C" + result := '"' + strtran(xField, '"', ' ') + '"' + elseif cType == "D" + result := '"' + StrZero(month(xField),2) + '/' + StrZero(day(xField),2) + '/' + StrZero(Year(xField),4) + '"' + elseif cType == "N" + result := str(xField) + elseif cType == "L" + result := iif( xField, '1', '0' ) + end + +return result + + +Static Function StructConvert( aStru, db, dialect) + Local aNew := {} + Local cField + Local nType + Local cType + Local nSize + Local nDec + Local cTable + Local cDomain + Local i + Local qry + Local cQuery + Local aDomains := {} + Local fetch_stmt + Local nVal + + Local xTables := '' + Local xFields := '' + + /* create table list and field list */ + + For i := 1 to Len(aStru) + xtables += DataToSql(aStru[i, 5]) + xfields += DataToSql(aStru[i, 1]) + + if i <> len(aStru) + xtables += ',' + xfields += ',' + end + Next + + /* Look for domains */ + cQuery := 'select rdb$relation_name, rdb$field_name, rdb$field_source ' + cQuery += ' from rdb$relation_fields ' + cQuery += ' where rdb$field_name not like "RDB$%" ' + cQuery += ' and rdb$relation_name in (' + xtables + ')' + cQuery += ' and rdb$field_name in (' + xfields + ')' + + qry := FBQuery(db, RemoveSpaces(cQuery), dialect) + + if ISARRAY(qry) + + do while (fetch_stmt := FBFetch(qry)) == 0 + aadd( aDomains, { FBGetdata(qry, 1), FBGetdata(qry,2), FBGetdata(qry,3) } ) + end + + FBFree(qry) + + For i := 1 to Len(aStru) + cField := trim(aStru[i,1]) + nType := aStru[i,2] + nSize := aStru[i,3] + nDec := aStru[i,4] * -1 + cTable := trim(aStru[i,5]) + + nVal := AScan(aDomains, {|x| trim(x[1]) == cTable .and. trim(x[2]) == cField}) + + if nVal != 0 + cDomain := aDomains[ nVal, 3 ] + else + cDomain := '' + end + + switch nType + case SQL_TEXT + cType := "C" + exit + case SQL_VARYING + cType := "C" + exit + case SQL_SHORT + /* Firebird doesn't have boolean field, so if you define domain with BOOL then i will consider logical, ex: + create domain boolean_field as smallint default 0 not null check (value in (0,1)) */ + + if "BOOL" $ cDomain + cType := "L" + nSize := 1 + nDec := 0 + else + cType := "N" + nSize := 5 + end + exit + case SQL_LONG + cType := "N" + nSize := 9 + exit + case SQL_INT64 + cType := "N" + nSize := 9 + exit + case SQL_FLOAT + cType := "N" + nSize := 15 + exit + case SQL_DOUBLE + cType := "N" + nSize := 15 + exit + case SQL_TIMESTAMP + cType := "D" + nSize := 8 + exit + case SQL_TYPE_DATE + cType := "D" + nSize := 8 + exit + case SQL_TYPE_TIME + cType := "C" + nSize := 8 + exit + case SQL_BLOB + cType := "M" + nSize := 10 + exit + otherwise + cType := "C" + nDec := 0 + end + + aadd( aNew, { cField, cType, nSize, nDec, cTable, cDomain } ) + Next + End + +return aNew + +Static Function RemoveSpaces( cQuery ) + Do While AT(" ", cQuery) != 0 + cQuery := Strtran(cQuery, " ", " ") + end +Return cQuery diff --git a/harbour/contrib/freeimage/Makefile b/harbour/contrib/freeimage/Makefile new file mode 100644 index 0000000000..cd05884018 --- /dev/null +++ b/harbour/contrib/freeimage/Makefile @@ -0,0 +1,15 @@ +# +# $Id$ +# + +ROOT = ../../ + +C_SOURCES = \ + fi_winfu.c \ + fi_wrp.c \ + +PRG_SOURCES= \ + +LIBNAME=fi_lib + +include $(TOP)$(ROOT)config/lib.cf diff --git a/harbour/contrib/freeimage/common.mak b/harbour/contrib/freeimage/common.mak new file mode 100644 index 0000000000..55ce756219 --- /dev/null +++ b/harbour/contrib/freeimage/common.mak @@ -0,0 +1,18 @@ +# +# $Id$ +# + +LIBNAME = fi_lib + +LIB_PATH = $(LIB_DIR)\$(LIBNAME)$(LIBEXT) + +# +# LIB rules +# + +LIB_OBJS = \ + $(OBJ_DIR)\fi_winfu$(OBJEXT) \ + $(OBJ_DIR)\fi_wrp$(OBJEXT) \ + +all: \ + $(LIB_PATH) \ diff --git a/harbour/contrib/freeimage/fi_winfu.c b/harbour/contrib/freeimage/fi_winfu.c new file mode 100644 index 0000000000..cfb2b68d9b --- /dev/null +++ b/harbour/contrib/freeimage/fi_winfu.c @@ -0,0 +1,245 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * FreeImage windows specific functions. + * + * Copyright 2005 Francesco Saverio Giudice + * www - http://www.xharbour.org http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* + * + * See doc/license files for licensing terms. + * + */ + +/* NOTE: we need this to prevent base types redefinition */ +#define _CLIPDEFS_H +#if defined(HB_OS_WIN_32_USED) + #include +#endif + +#include "hbapi.h" +#include "hbapiitm.h" +#include "hbstack.h" +#include "hbapierr.h" +#include "hbapifs.h" +//#include "hrbdll.h" +#include "hbvm.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "FreeImage.h" + +// -------------------------------------------------------------------------- +// Convert from FreeImage to HBITMAP ---------------------------------------- +// -------------------------------------------------------------------------- +#if ( defined(HB_OS_WIN_32) || defined(__WIN32__) ) + +// implementation: HBITMAP bitmap = FI_FiToBitmap( FIBITMAP *dib ); +HB_FUNC( FI_FITOBITMAP ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + HBITMAP bitmap; + HDC hDC; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function */ + hDC = GetDC( NULL ); + bitmap = CreateDIBitmap(hDC, FreeImage_GetInfoHeader(dib), + CBM_INIT, FreeImage_GetBits(dib), + FreeImage_GetInfo(dib), DIB_RGB_COLORS); + ReleaseDC( NULL, hDC ); + + /* return value */ + if ( bitmap != NULL ) + { + hb_retnl( (LONG) bitmap ); + } + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_FITOBITMAP", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// -------------------------------------------------------------------------- +// Convert from HBITMAP to FreeImage ---------------------------------------- +// -------------------------------------------------------------------------- + +// implementation: FIBITMAP *dib = FI_BitmapToFi( HBITMAP bitmap ); +HB_FUNC( FI_BITMAPTOFI ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + HBITMAP bitmap; + + /* Retrieve parameters */ + bitmap = (HBITMAP) hb_parnl( 1 ); + + /* run function */ + dib = NULL; + + if( bitmap ) { + BITMAP bm; + HDC hDC; + int Success; + + GetObject( bitmap, sizeof(BITMAP), (LPSTR) &bm ); + dib = FreeImage_Allocate(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0, 0, 0); + hDC = GetDC( NULL ); + Success = GetDIBits( hDC, bitmap, 0, FreeImage_GetHeight(dib), + FreeImage_GetBits(dib), FreeImage_GetInfo(dib), DIB_RGB_COLORS); + ReleaseDC( NULL, hDC ); + + HB_SYMBOL_UNUSED( Success ); + } + + /* return value */ + if ( dib != NULL ) + { + hb_retptr( dib ); + } + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_BITMAPTOFI", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// -------------------------------------------------------------------------- +// Draw an image in a window Box -------------------------------------------- +// -------------------------------------------------------------------------- + +// implementation: int scanlines = FI_WinDraw( FIBITMAP *dib, HDC hDC, nTop, nLeft, nBottom, nRight ); +HB_FUNC( FI_WINDRAW ) +{ + if ( hb_pcount() == 6 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC && + hb_parinfo( 4 ) & HB_IT_NUMERIC && + hb_parinfo( 5 ) & HB_IT_NUMERIC && + hb_parinfo( 6 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + HDC hDC; + RECT rcDest; + int scanlines; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + hDC = (HDC) hb_parnl( 2 ); + rcDest.top = hb_parni( 3 ); + rcDest.left = hb_parni( 4 ); + rcDest.bottom = hb_parni( 5 ); + rcDest.right = hb_parni( 6 ); + + /* run function */ + SetStretchBltMode(hDC, COLORONCOLOR); + + scanlines = StretchDIBits(hDC, rcDest.left, + rcDest.top, + rcDest.right-rcDest.left, + rcDest.bottom-rcDest.top, + 0, 0, FreeImage_GetWidth(dib), FreeImage_GetHeight(dib), + FreeImage_GetBits(dib), FreeImage_GetInfo(dib), + DIB_RGB_COLORS, SRCCOPY); + + /* return value */ + hb_retni( scanlines ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_WINDRAW", 6, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), + hb_paramError( 4 ), hb_paramError( 5 ), hb_paramError( 6 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +#endif // ( defined(HB_OS_WIN_32) || defined(__WIN32__) ) diff --git a/harbour/contrib/freeimage/fi_wrp.c b/harbour/contrib/freeimage/fi_wrp.c new file mode 100644 index 0000000000..b1bc8f6e14 --- /dev/null +++ b/harbour/contrib/freeimage/fi_wrp.c @@ -0,0 +1,2877 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * FreeImage graphic library low level (client api) interface code. + * + * Copyright 2005 Francesco Saverio Giudice + * www - http://www.xharbour.org http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* NOTE: we need this to prevent base types redefinition */ +#define _CLIPDEFS_H + +#include "hbapi.h" +#include "hbapiitm.h" +#include "hbstack.h" +#include "hbapierr.h" +#include "hbapifs.h" +//#include "hrbdll.h" +#include "hbvm.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "FreeImage.h" + +/* ************************* WRAPPED FUNCTIONS ****************************** */ + +// static for error handler (see below FI_SETOUTPUTMESSAGE ) +static void *pErrorHandler = NULL; + +// -------------------------------------------------------------------------- +// Init / Error routines ---------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_Initialise(BOOL load_local_plugins_only FI_DEFAULT(FALSE)); +HB_FUNC( FI_INITIALISE ) +{ + BOOL bLoadPluginsOnly; + + /* Retrieve parameters */ + bLoadPluginsOnly = ( hb_parinfo( 1 ) & HB_IT_LOGICAL ? hb_parl( 1 ) : FALSE ); + + /* Run function */ + FreeImage_Initialise( bLoadPluginsOnly ); +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_DeInitialise(void); +HB_FUNC( FI_DEINITIALISE ) +{ + /* Run function */ + FreeImage_DeInitialise(); +} + +// -------------------------------------------------------------------------- +// Version routines --------------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API const char *DLL_CALLCONV FreeImage_GetVersion(void); +HB_FUNC( FI_GETVERSION ) +{ + /* Run function & return value */ + hb_retc( FreeImage_GetVersion() ); +} + +// -------------------------------------------------------------------------- + +// DLL_API const char *DLL_CALLCONV FreeImage_GetCopyrightMessage(void); +HB_FUNC( FI_GETCOPYRIGHTMESSAGE ) +{ + /* Run function & return value */ + hb_retc( FreeImage_GetCopyrightMessage() ); +} + +// -------------------------------------------------------------------------- +// Message output functions ------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_OutputMessageProc(int fif, const char *fmt, ...); + +// typedef void (*FreeImage_OutputMessageFunction)(FREE_IMAGE_FORMAT fif, const char *msg); +// DLL_API void DLL_CALLCONV FreeImage_SetOutputMessage(FreeImage_OutputMessageFunction omf); + +// implementation: void FreeImage_SetOutputMessage( pFunctionPointer ) + +/** +FreeImage error handler +@param fif Format / Plugin responsible for the error +@param message Error message +*/ +void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) +{ + const char *format; + PHB_SYMB pSymbol; + + if ( pErrorHandler == NULL ) + { + // Do nothing + return; + } + + pSymbol = (PHB_SYMB) pErrorHandler; + + //TraceLog( NULL, "ErrorHandle %p\n\r", pErrorHandler ); + + if( pSymbol == NULL ) + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, "FreeImageErrorHandler", 1, hb_paramError( 1 ) ); + return; + } + + format = FreeImage_GetFormatFromFIF(fif); + + /* launch error function at prg level */ + hb_vmPushSymbol( pSymbol ); + hb_vmPushNil(); + hb_vmPushString( format, strlen( format ) ); + hb_vmPushString( message, strlen( message ) ); + hb_vmDo( 2 ); + +} + +HB_FUNC( FI_SETOUTPUTMESSAGE ) +{ + pErrorHandler = NULL; + FreeImage_SetOutputMessage(FreeImageErrorHandler); + +/* TraceLog( NULL, "PCount = %i\n\r", hb_pcount() ); */ + + if ( hb_pcount() == 1 ) + { + if ( hb_parinfo( 1 ) & HB_IT_POINTER ) + { + // Set the pointer + pErrorHandler = hb_parptr( 1 ); + } + else if ( ISNIL( 1 ) ) + { + // do nothing + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SETOUTPUTMESSAGE", 1, + hb_paramError( 1 ) + ); + return; + } + } + } +} +// -------------------------------------------------------------------------- +// Allocate / Clone / Unload routines --------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0)); +HB_FUNC( FI_ALLOCATE ) +{ + if ( hb_pcount() >= 3 && + hb_parinfo( 1 ) & HB_IT_NUMERIC && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC + ) + { + int width, height, bpp; + UINT red_mask, green_mask, blue_mask; + + /* Retrieve parameters */ + width = hb_parni( 1 ); + height = hb_parni( 2 ); + bpp = hb_parni( 3 ); + red_mask = ( hb_parinfo( 4 ) & HB_IT_NUMERIC ? hb_parni( 4 ) : 0 ); + green_mask = ( hb_parinfo( 5 ) & HB_IT_NUMERIC ? hb_parni( 5 ) : 0 ); + blue_mask = ( hb_parinfo( 6 ) & HB_IT_NUMERIC ? hb_parni( 6 ) : 0 ); + + /* run function & return value */ + hb_retptr( FreeImage_Allocate(width, height, bpp, red_mask, green_mask, blue_mask) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ALLOCATE", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp FI_DEFAULT(8), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0)); +HB_FUNC( FI_ALLOCATET ) +{ + if ( hb_pcount() >= 3 && + hb_parinfo( 1 ) & HB_IT_NUMERIC && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC + ) + { + FREE_IMAGE_TYPE type; + int width, height, bpp; + UINT red_mask, green_mask, blue_mask; + + /* Retrieve parameters */ + type = hb_parni( 1 ); + width = hb_parni( 2 ); + height = hb_parni( 3 ); + bpp = ( hb_parinfo( 3 ) & HB_IT_NUMERIC ? hb_parni( 3 ) : 8 ); + red_mask = ( hb_parinfo( 4 ) & HB_IT_NUMERIC ? hb_parni( 4 ) : 0 ); + green_mask = ( hb_parinfo( 5 ) & HB_IT_NUMERIC ? hb_parni( 5 ) : 0 ); + blue_mask = ( hb_parinfo( 6 ) & HB_IT_NUMERIC ? hb_parni( 6 ) : 0 ); + + /* run function & return value */ + hb_retptr( FreeImage_AllocateT(type, width, height, bpp, red_mask, green_mask, blue_mask) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ALLOCATET", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib); +HB_FUNC( FI_CLONE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + FIBITMAP *fiClonePtr; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function */ + fiClonePtr = FreeImage_Clone( dib ); + + /* return value */ + if ( fiClonePtr != NULL ) + { + hb_retptr( fiClonePtr ); + } + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CLONE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_Unload(FIBITMAP *dib); +HB_FUNC( FI_UNLOAD ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function */ + FreeImage_Unload( dib ); + + /* return value */ + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_UNLOAD", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- +// Load / Save routines ----------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags FI_DEFAULT(0)); +HB_FUNC( FI_LOAD ) +{ + if ( hb_pcount() == 3 && + hb_parinfo( 1 ) & HB_IT_NUMERIC && + hb_parinfo( 2 ) & HB_IT_STRING && + hb_parinfo( 3 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + FREE_IMAGE_FORMAT fif; + const char *filename; + int flags; + + /* Retrieve parameters */ + fif = hb_parni( 1 ); + filename = hb_parcx( 2 ); + flags = hb_parni( 3 ); + + /* run function */ + dib = FreeImage_Load(fif, filename, flags); + + /* return value */ + if ( dib != NULL ) + { + hb_retptr( dib ); + } + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_LOAD", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, int flags FI_DEFAULT(0)); +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0)); + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags FI_DEFAULT(0)); +HB_FUNC( FI_SAVE ) +{ + if ( hb_pcount() == 4 && + hb_parinfo( 1 ) & HB_IT_NUMERIC && + hb_parinfo( 2 ) & HB_IT_POINTER && + hb_parinfo( 3 ) & HB_IT_STRING && + hb_parinfo( 4 ) & HB_IT_NUMERIC + ) + { + FREE_IMAGE_FORMAT fif; + FIBITMAP *dib; + const char *filename; + int flags; + + /* Retrieve parameters */ + fif = hb_parni( 1 ); + dib = hb_parptr( 2 ); + filename = hb_parcx( 3 ); + flags = hb_parni( 4 ); + + /* run function & return value */ + hb_retl( FreeImage_Save(fif, dib, filename, flags) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SAVE", 4, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const wchar_t *filename, int flags FI_DEFAULT(0)); +// DLL_API BOOL DLL_CALLCONV FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0)); + +// -------------------------------------------------------------------------- +// Memory I/O stream routines ----------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FIMEMORY *DLL_CALLCONV FreeImage_OpenMemory(BYTE *data FI_DEFAULT(0), DWORD size_in_bytes FI_DEFAULT(0)); +// DLL_API void DLL_CALLCONV FreeImage_CloseMemory(FIMEMORY *stream); +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags FI_DEFAULT(0)); +// DLL_API BOOL DLL_CALLCONV FreeImage_SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FIMEMORY *stream, int flags FI_DEFAULT(0)); +// DLL_API long DLL_CALLCONV FreeImage_TellMemory(FIMEMORY *stream); +// DLL_API BOOL DLL_CALLCONV FreeImage_SeekMemory(FIMEMORY *stream, long offset, int origin); +// DLL_API BOOL DLL_CALLCONV FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes); + +// -------------------------------------------------------------------------- +// Plugin Interface --------------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_RegisterLocalPlugin(FI_InitProc proc_address, const char *format FI_DEFAULT(0), const char *description FI_DEFAULT(0), const char *extension FI_DEFAULT(0), const char *regexpr FI_DEFAULT(0)); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_RegisterExternalPlugin(const char *path, const char *format FI_DEFAULT(0), const char *description FI_DEFAULT(0), const char *extension FI_DEFAULT(0), const char *regexpr FI_DEFAULT(0)); +// DLL_API int DLL_CALLCONV FreeImage_GetFIFCount(void); +// DLL_API int DLL_CALLCONV FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif, BOOL enable); +// DLL_API int DLL_CALLCONV FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFormat(const char *format); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromMime(const char *mime); +// DLL_API const char *DLL_CALLCONV FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif); +// DLL_API const char *DLL_CALLCONV FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif); +// DLL_API const char *DLL_CALLCONV FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif); +// DLL_API const char *DLL_CALLCONV FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif); +// DLL_API const char *DLL_CALLCONV FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilename(const char *filename); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilenameU(const wchar_t *filename); +// DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif); +// DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif); +// DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int bpp); +// DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type); +// DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif); + +// -------------------------------------------------------------------------- +// Multipaging interface ---------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FIMULTIBITMAP * DLL_CALLCONV FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory FI_DEFAULT(FALSE), int flags FI_DEFAULT(0)); +HB_FUNC( FI_OPENMULTIBITMAP ) +{ + if ( hb_pcount() >= 4 && + hb_parinfo( 1 ) & HB_IT_NUMERIC && + hb_parinfo( 2 ) & HB_IT_STRING && + hb_parinfo( 3 ) & HB_IT_LOGICAL && + hb_parinfo( 4 ) & HB_IT_LOGICAL + ) + { + FIMULTIBITMAP *dib; + FREE_IMAGE_FORMAT fif; + const char *filename; + BOOL create_new; + BOOL read_only; + BOOL keep_cache_in_memory; + int flags; + + /* Retrieve parameters */ + fif = hb_parni( 1 ); + filename = hb_parcx( 2 ); + create_new = hb_parl( 3 ); + read_only = hb_parl( 4 ); + keep_cache_in_memory = ( hb_parinfo( 5 ) & HB_IT_LOGICAL ? hb_parl( 5 ) : FALSE ); + flags = ( hb_parinfo( 6 ) & HB_IT_NUMERIC ? hb_parni( 6 ) : 0 ); + + /* run function */ + dib = FreeImage_OpenMultiBitmap(fif, filename, create_new, read_only, keep_cache_in_memory, flags); + + /* return value */ + if ( dib != NULL ) + { + hb_retptr( dib ); + } + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_OPENMULTIBITMAP", 4, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags FI_DEFAULT(0)); +HB_FUNC( FI_CLOSEMULTIBITMAP ) +{ + if ( hb_pcount() >= 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIMULTIBITMAP *bitmap; + int flags; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + flags = ( hb_parinfo( 2 ) & HB_IT_NUMERIC ? hb_parni( 2 ) : 0 ); + + /* run function & return value */ + hb_retl( FreeImage_CloseMultiBitmap(bitmap, flags) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CLOSEMULTIBITMAP", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API int DLL_CALLCONV FreeImage_GetPageCount(FIMULTIBITMAP *bitmap); +HB_FUNC( FI_GETPAGECOUNT ) +{ + if ( hb_pcount() >= 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIMULTIBITMAP *bitmap; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetPageCount(bitmap) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETPAGECOUNT", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data); +HB_FUNC( FI_APPENDPAGE ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_POINTER + ) + { + FIMULTIBITMAP *bitmap; + FIBITMAP *data; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + data = hb_parptr( 2 ); + + /* run function & return value */ + FreeImage_AppendPage(bitmap, data); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_APPENDPAGE", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data); +HB_FUNC( FI_INSERTPAGE ) +{ + if ( hb_pcount() == 3 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_POINTER + ) + { + FIMULTIBITMAP *bitmap; + int page; + FIBITMAP *data; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + page = hb_parni( 2 ) - 1; // 0-based index + data = hb_parptr( 3 ); + + /* run function & return value */ + FreeImage_InsertPage(bitmap, page, data); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_INSERTPAGE", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page); +HB_FUNC( FI_DELETEPAGE ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIMULTIBITMAP *bitmap; + int page; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + page = hb_parni( 2 ) - 1; // 0-based index + + /* run function & return value */ + FreeImage_DeletePage(bitmap, page); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_DELETEPAGE", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP * DLL_CALLCONV FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page); +HB_FUNC( FI_LOCKPAGE ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIMULTIBITMAP *bitmap; + int page; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + page = hb_parni( 2 ) - 1; // 0-based index + + /* run function & return value */ + hb_retptr( FreeImage_LockPage(bitmap, page) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_LOCKPAGE", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed); +HB_FUNC( FI_UNLOCKPAGE ) +{ + if ( hb_pcount() == 3 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_LOGICAL + ) + { + FIMULTIBITMAP *bitmap; + FIBITMAP *page; + BOOL changed; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + page = hb_parptr( 2 ); + changed = hb_parl( 3 ); + + /* run function & return value */ + FreeImage_UnlockPage(bitmap, page, changed); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_UNLOCKPAGE", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source); +HB_FUNC( FI_MOVEPAGE ) +{ + if ( hb_pcount() == 3 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC + ) + { + FIMULTIBITMAP *bitmap; + int target, source; + + /* Retrieve parameters */ + bitmap = hb_parptr( 1 ); + target = hb_parni( 2 ); + source = hb_parni( 3 ); + + /* run function & return value */ + hb_retl( FreeImage_MovePage(bitmap, target, source) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_MOVEPAGE", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count); + +// -------------------------------------------------------------------------- +// Filetype request routines ------------------------------------------------ +// -------------------------------------------------------------------------- + +// -------------------------------------------------------------------------- + +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size FI_DEFAULT(0)); +HB_FUNC( FI_GETFILETYPE ) +{ + if ( hb_pcount() >= 1 && + hb_parinfo( 1 ) & HB_IT_STRING + ) + { + const char *filename; + int size; + + /* Retrieve parameters */ + filename = hb_parcx( 1 ); + size = ( hb_parinfo( 2 ) & HB_IT_NUMERIC ? hb_parni( 1 ) : 0 ); + + /* run function & return value */ + hb_retni( FreeImage_GetFileType(filename, size) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETFILETYPE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeU(const wchar_t *filename, int size FI_DEFAULT(0)); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size FI_DEFAULT(0)); +// DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size FI_DEFAULT(0)); + +// -------------------------------------------------------------------------- +// Image type request routine ----------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FREE_IMAGE_TYPE DLL_CALLCONV FreeImage_GetImageType(FIBITMAP *dib); +HB_FUNC( FI_GETIMAGETYPE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetImageType(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETIMAGETYPE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- +// FreeImage helper routines ------------------------------------------------ +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_IsLittleEndian(void); +HB_FUNC( FI_ISLITTLEENDIAN ) +{ + /* run function & return value */ + hb_retl( FreeImage_IsLittleEndian() ); +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_LookupX11Color(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue); +// DLL_API BOOL DLL_CALLCONV FreeImage_LookupSVGColor(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue); + + +// -------------------------------------------------------------------------- +// Pixel access routines ---------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API BYTE *DLL_CALLCONV FreeImage_GetBits(FIBITMAP *dib); +HB_FUNC( FI_GETBITS ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_GetBits(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETBITS", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BYTE *DLL_CALLCONV FreeImage_GetScanLine(FIBITMAP *dib, int scanline); +HB_FUNC( FI_GETSCANLINE ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + int scanline; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + scanline = hb_parni( 2 ); + + /* run function & return value */ + hb_retptr( FreeImage_GetScanLine(dib, scanline) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETSCANLINE", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API BOOL DLL_CALLCONV FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value); +// DLL_API BOOL DLL_CALLCONV FreeImage_GetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value); + +// -------------------------------------------------------------------------- +// DIB info routines -------------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetColorsUsed(FIBITMAP *dib); +HB_FUNC( FI_GETCOLORSUSED ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetColorsUsed(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETCOLORSUSED", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetBPP(FIBITMAP *dib); +HB_FUNC( FI_GETBPP ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value*/ + hb_retnl( FreeImage_GetBPP(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETBPP", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetWidth(FIBITMAP *dib); +HB_FUNC( FI_GETWIDTH ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetWidth(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETWIDTH", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetHeight(FIBITMAP *dib); +HB_FUNC( FI_GETHEIGHT ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetHeight(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETHEIGHT", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetLine(FIBITMAP *dib); +HB_FUNC( FI_GETLINE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetLine(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETLINE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetPitch(FIBITMAP *dib); +HB_FUNC( FI_GETPITCH ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetPitch(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETPITCH", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetDIBSize(FIBITMAP *dib); +HB_FUNC( FI_GETDIBSIZE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetDIBSize(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETDIBSIZE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API RGBQUAD *DLL_CALLCONV FreeImage_GetPalette(FIBITMAP *dib); +HB_FUNC( FI_GETPALETTE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_GetPalette(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETPALETTE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetDotsPerMeterX(FIBITMAP *dib); +HB_FUNC( FI_GETDOTSPERMETERX ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetDotsPerMeterX(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETDOTSPERMETERX", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetDotsPerMeterY(FIBITMAP *dib); +HB_FUNC( FI_GETDOTSPERMETERY ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retnl( FreeImage_GetDotsPerMeterY(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETDOTSPERMETERY", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res); +HB_FUNC( FI_SETDOTSPERMETERX ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + UINT res; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + res = hb_parni( 2 ); + + /* run function & return value */ + FreeImage_SetDotsPerMeterX(dib, res); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SETDOTSPERMETERX", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res); +HB_FUNC( FI_SETDOTSPERMETERY ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + UINT res; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + res = hb_parni( 2 ); + + /* run function & return value */ + FreeImage_SetDotsPerMeterY(dib, res); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SETDOTSPERMETERY", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API BITMAPINFOHEADER *DLL_CALLCONV FreeImage_GetInfoHeader(FIBITMAP *dib); +HB_FUNC( FI_GETINFOHEADER ) +{ + + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + // We need not worry about Memory Management - will be automatically released! + //BITMAPINFOHEADER *bmpinfoheader = (BITMAPINFOHEADER *) hb_xgrab( sizeof( BITMAPINFOHEADER ) ); + BITMAPINFOHEADER *bmpinfoheader; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + bmpinfoheader = FreeImage_GetInfoHeader(dib); + + //hb_retclenAdoptRaw( (char *) bmpinfoheader, sizeof( BITMAPINFOHEADER ) ); + hb_retptr( bmpinfoheader ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETINFOHEADER", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BITMAPINFO *DLL_CALLCONV FreeImage_GetInfo(FIBITMAP *dib); +HB_FUNC( FI_GETINFO ) +{ + + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + BITMAPINFO *bmpinfo; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + bmpinfo = FreeImage_GetInfo(dib); + + hb_retptr( bmpinfo ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETINFO", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FREE_IMAGE_COLOR_TYPE DLL_CALLCONV FreeImage_GetColorType(FIBITMAP *dib); +HB_FUNC( FI_GETCOLORTYPE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetColorType(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETCOLORTYPE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API unsigned DLL_CALLCONV FreeImage_GetRedMask(FIBITMAP *dib); +HB_FUNC( FI_GETREDMASK ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetRedMask(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETREDMASK", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetGreenMask(FIBITMAP *dib); +HB_FUNC( FI_GETGREENMASK ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetGreenMask(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETGREENMASK", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API unsigned DLL_CALLCONV FreeImage_GetBlueMask(FIBITMAP *dib); +HB_FUNC( FI_GETBLUEMASK ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetBlueMask(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETBLUEMASK", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API unsigned DLL_CALLCONV FreeImage_GetTransparencyCount(FIBITMAP *dib); +HB_FUNC( FI_GETTRANSPARENCYCOUNT ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retni( FreeImage_GetTransparencyCount(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETTRANSPARENCYCOUNT", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BYTE * DLL_CALLCONV FreeImage_GetTransparencyTable(FIBITMAP *dib); +HB_FUNC( FI_GETTRANSPARENCYTABLE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_GetTransparencyTable(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETTRANSPARENCYTABLE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_SetTransparent(FIBITMAP *dib, BOOL enabled); +HB_FUNC( FI_SETTRANSPARENT ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_LOGICAL + ) + { + FIBITMAP *dib; + BOOL enabled; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + enabled = hb_parl( 2 ); + + /* run function & return value */ + FreeImage_SetTransparent(dib, enabled); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SETTRANSPARENT", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_SetTransparencyTable(FIBITMAP *dib, BYTE *table, int count); +HB_FUNC( FI_SETTRANSPARENCYTABLE ) +{ + if ( hb_pcount() == 3 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_POINTER && + hb_parinfo( 3 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + BYTE *table; + int count; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + table = hb_parptr( 2 ); + count = hb_parni( 3 ); + + /* run function & return value */ + FreeImage_SetTransparencyTable(dib, table, count); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SETTRANSPARENCYTABLE", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_IsTransparent(FIBITMAP *dib); +HB_FUNC( FI_ISTRANSPARENT ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retl( FreeImage_IsTransparent(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ISTRANSPARENT", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API BOOL DLL_CALLCONV FreeImage_HasBackgroundColor(FIBITMAP *dib); +HB_FUNC( FI_HASBACKGROUNDCOLOR ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retl( FreeImage_HasBackgroundColor(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_HASBACKGROUNDCOLOR", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_GetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor); +HB_FUNC( FI_GETBACKGROUNDCOLOR ) +{ + + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER //&& + //hb_parinfo( 2 ) & HB_IT_STRING + ) + { + FIBITMAP *dib; + RGBQUAD *bkcolor; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + //bkcolor = (RGBQUAD * ) hb_param( 2, HB_IT_STRING )->item.asString.value; + //bkcolor = hb_parptr( 2 ); + + /* run function & return value */ + //hb_retl( FreeImage_GetBackgroundColor(dib, bkcolor) ); + FreeImage_GetBackgroundColor(dib, bkcolor); + //hb_storptr( bkcolor, 2 ); + hb_retptr( bkcolor ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETBACKGROUNDCOLOR", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_SetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor); +HB_FUNC( FI_SETBACKGROUNDCOLOR ) +{ + + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + //hb_parinfo( 2 ) & HB_IT_POINTER + hb_parinfo( 2 ) & HB_IT_STRING + ) + { + FIBITMAP *dib; + RGBQUAD *bkcolor; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + bkcolor = (RGBQUAD * ) hb_itemGetCPtr( hb_param( 2, HB_IT_STRING ) ); + //bkcolor = hb_parptr( 2 ); + + /* run function & return value */ + hb_retl( FreeImage_SetBackgroundColor(dib, bkcolor) ); + //FreeImage_GetBackgroundColor(dib, bkcolor); + //hb_retptr( bkcolor ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_SETBACKGROUNDCOLOR", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + + + +// -------------------------------------------------------------------------- +// ICC profile routines ----------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API FIICCPROFILE *DLL_CALLCONV FreeImage_GetICCProfile(FIBITMAP *dib); +HB_FUNC( FI_GETICCPROFILE ) +{ + + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_GetICCProfile(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETICCPROFILE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIICCPROFILE *DLL_CALLCONV FreeImage_CreateICCProfile(FIBITMAP *dib, void *data, long size); +HB_FUNC( FI_CREATEICCPROFILE ) +{ + + if ( hb_pcount() == 3 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_POINTER && + hb_parinfo( 3 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + void *data; + long size; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + data = hb_parptr( 2 ); + size = hb_parnl( 3 ); + + /* run function & return value */ + hb_retptr( FreeImage_CreateICCProfile(dib, data, size) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CREATEICCPROFILE", 3, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_DestroyICCProfile(FIBITMAP *dib); +HB_FUNC( FI_DESTROYICCPROFILE ) +{ + + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + FreeImage_DestroyICCProfile(dib); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_DESTROYICCPROFILE", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- +// Line conversion routines ------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To4(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To4(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To4_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To4_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To4(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To4(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16_565_To16_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To16_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To16_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16_555_To16_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To16_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To16_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels); +// DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels); + +// -------------------------------------------------------------------------- +// Smart conversion routines ------------------------------------------------ +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo4Bits(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTO4BITS ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertTo4Bits(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTO4BITS", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo8Bits(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTO8BITS ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertTo8Bits(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTO8BITS", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToGreyscale(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTOGREYSCALE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertToGreyscale(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTOGREYSCALE", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo16Bits555(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTO16BITS555 ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertTo16Bits555(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTO16BITS555", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo16Bits565(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTO16BITS565 ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertTo16Bits565(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTO16BITS565", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo24Bits(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTO24BITS ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertTo24Bits(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTO24BITS", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo32Bits(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTO32BITS ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertTo32Bits(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTO32BITS", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ColorQuantize(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize); +HB_FUNC( FI_COLORQUANTIZE ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + FREE_IMAGE_QUANTIZE quantize; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + quantize = hb_parni( 2 ); + + /* run function & return value */ + hb_retptr( FreeImage_ColorQuantize(dib, quantize) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_COLORQUANTIZE", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize FI_DEFAULT(FIQ_WUQUANT), int PaletteSize FI_DEFAULT(256), int ReserveSize FI_DEFAULT(0), RGBQUAD *ReservePalette FI_DEFAULT(NULL)); +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Threshold(FIBITMAP *dib, BYTE T); + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Dither(FIBITMAP *dib, FREE_IMAGE_DITHER algorithm); +HB_FUNC( FI_DITHER ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + FREE_IMAGE_DITHER algorithm; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + algorithm = hb_parni( 2 ); + + /* run function & return value */ + hb_retptr( FreeImage_Dither(dib, algorithm) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_DITHER", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertFromRawBits(BYTE *bits, int width, int height, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown FI_DEFAULT(FALSE)); +// DLL_API void DLL_CALLCONV FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown FI_DEFAULT(FALSE)); +// +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGBF(FIBITMAP *dib); +HB_FUNC( FI_CONVERTTORGBF ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retptr( FreeImage_ConvertToRGBF(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTORGBF", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToStandardType(FIBITMAP *src, BOOL scale_linear FI_DEFAULT(TRUE)); +HB_FUNC( FI_CONVERTTOSTANDARDTYPE ) +{ + if ( hb_pcount() >= 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + BOOL scale_linear; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + scale_linear = ( hb_parinfo( 2 ) & HB_IT_LOGICAL ) ? hb_parl( 2 ) : TRUE; + + /* run function & return value */ + hb_retptr( FreeImage_ConvertToStandardType(dib, scale_linear) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTOSTANDARDTYPE", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear FI_DEFAULT(TRUE)); +HB_FUNC( FI_CONVERTTOTYPE ) +{ + if ( hb_pcount() >= 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + FREE_IMAGE_TYPE dst_type; + BOOL scale_linear; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + dst_type = hb_parni( 2 ); + scale_linear = ( hb_parinfo( 3 ) & HB_IT_LOGICAL ) ? hb_parl( 3 ) : TRUE; + + /* run function & return value */ + hb_retptr( FreeImage_ConvertToType(dib, dst_type, scale_linear) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_CONVERTTOTYPE", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// +// // tone mapping operators +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ToneMapping(FIBITMAP *dib, FREE_IMAGE_TMO tmo, double first_param FI_DEFAULT(0), double second_param FI_DEFAULT(0)); +// DLL_API FIBITMAP* DLL_CALLCONV FreeImage_TmoDrago03(FIBITMAP *src, double gamma FI_DEFAULT(2.2), double exposure FI_DEFAULT(0)); +// DLL_API FIBITMAP* DLL_CALLCONV FreeImage_TmoReinhard05(FIBITMAP *src, double intensity FI_DEFAULT(0), double contrast FI_DEFAULT(0)); + +// -------------------------------------------------------------------------- +// ZLib interface ----------------------------------------------------------- +// -------------------------------------------------------------------------- + +// DLL_API DWORD DLL_CALLCONV FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +// DLL_API DWORD DLL_CALLCONV FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +// DLL_API DWORD DLL_CALLCONV FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +// DLL_API DWORD DLL_CALLCONV FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +// DLL_API DWORD DLL_CALLCONV FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size); + +// -------------------------------------------------------------------------- +// Metadata routines -------------------------------------------------------- +// -------------------------------------------------------------------------- + +// tag creation / destruction +// DLL_API FITAG *DLL_CALLCONV FreeImage_CreateTag(); +// DLL_API void DLL_CALLCONV FreeImage_DeleteTag(FITAG *tag); +// DLL_API FITAG *DLL_CALLCONV FreeImage_CloneTag(FITAG *tag); + +// tag getters and setters +// DLL_API const char *DLL_CALLCONV FreeImage_GetTagKey(FITAG *tag); +// DLL_API const char *DLL_CALLCONV FreeImage_GetTagDescription(FITAG *tag); +// DLL_API WORD DLL_CALLCONV FreeImage_GetTagID(FITAG *tag); +// DLL_API FREE_IMAGE_MDTYPE DLL_CALLCONV FreeImage_GetTagType(FITAG *tag); +// DLL_API DWORD DLL_CALLCONV FreeImage_GetTagCount(FITAG *tag); +// DLL_API DWORD DLL_CALLCONV FreeImage_GetTagLength(FITAG *tag); +// DLL_API const void *DLL_CALLCONV FreeImage_GetTagValue(FITAG *tag); +// +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagKey(FITAG *tag, const char *key); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagDescription(FITAG *tag, const char *description); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagID(FITAG *tag, WORD id); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagCount(FITAG *tag, DWORD count); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagLength(FITAG *tag, DWORD length); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetTagValue(FITAG *tag, const void *value); + +// iterator +// DLL_API FIMETADATA *DLL_CALLCONV FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag); +// DLL_API BOOL DLL_CALLCONV FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag); +// DLL_API void DLL_CALLCONV FreeImage_FindCloseMetadata(FIMETADATA *mdhandle); + +// metadata setter and getter +// DLL_API BOOL DLL_CALLCONV FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag); +// DLL_API BOOL DLL_CALLCONV FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag); + +// helpers +// DLL_API unsigned DLL_CALLCONV FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib); + +// tag to C string conversion +// DLL_API const char* DLL_CALLCONV FreeImage_TagToString(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make FI_DEFAULT(NULL)); + +// -------------------------------------------------------------------------- +// Image manipulation toolkit ----------------------------------------------- +// -------------------------------------------------------------------------- + +// rotation and flipping + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle); +HB_FUNC( FI_ROTATECLASSIC ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + double angle; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + angle = hb_parnd( 2 ); + + /* run function & return value */ + hb_retptr( FreeImage_RotateClassic(dib, angle) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ROTATECLASSIC", 2, + hb_paramError( 1 ), hb_paramError( 2 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask); +HB_FUNC( FI_ROTATEEX ) +{ + if ( hb_pcount() == 7 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC && + hb_parinfo( 4 ) & HB_IT_NUMERIC && + hb_parinfo( 5 ) & HB_IT_NUMERIC && + hb_parinfo( 6 ) & HB_IT_NUMERIC && + hb_parinfo( 7 ) & HB_IT_LOGICAL + ) + { + FIBITMAP *dib; + double angle, x_shift, y_shift, x_origin, y_origin; + BOOL use_mask; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + angle = hb_parnd( 2 ); + x_shift = hb_parnd( 3 ); + y_shift = hb_parnd( 4 ); + x_origin = hb_parnd( 5 ); + y_origin = hb_parnd( 6 ); + use_mask = hb_parl( 7 ); + + /* run function & return value */ + hb_retptr( FreeImage_RotateEx(dib, angle, x_shift, y_shift, x_origin, y_origin, use_mask) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ROTATEEX", 7, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ), + hb_paramError( 5 ), hb_paramError( 6 ), hb_paramError( 7 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_FlipHorizontal(FIBITMAP *dib); +HB_FUNC( FI_FLIPHORIZONTAL ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retl( FreeImage_FlipHorizontal(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_FLIPHORIZONTAL", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_FlipVertical(FIBITMAP *dib); +HB_FUNC( FI_FLIPVERTICAL ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retl( FreeImage_FlipVertical(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_FLIPVERTICAL", 1, + hb_paramError( 1 ) ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect FI_DEFAULT(FALSE)); + +// -------------------------------------------------------------------------- + +// upsampling / downsampling + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rescale(FIBITMAP *dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter); +HB_FUNC( FI_RESCALE ) +{ + if ( hb_pcount() == 4 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC && + hb_parinfo( 4 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + int dst_width, dst_height; + FREE_IMAGE_FILTER filter; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + dst_width = hb_parni( 2 ); + dst_height = hb_parni( 3 ); + filter = hb_parni( 4 ); + + /* run function & return value */ + hb_retptr( FreeImage_Rescale(dib, dst_width, dst_height, filter) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_RESCALE", 4, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// color manipulation routines (point operations) + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_AdjustCurve(FIBITMAP *dib, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel); + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_AdjustGamma(FIBITMAP *dib, double gamma); +HB_FUNC( FI_ADJUSTGAMMA ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + double gamma; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + gamma = hb_parnd( 2 ); + + /* run function & return value */ + hb_retl( FreeImage_AdjustGamma(dib, gamma) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ADJUSTGAMMA", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_AdjustBrightness(FIBITMAP *dib, double percentage); +HB_FUNC( FI_ADJUSTBRIGHTNESS ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + double percentage; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + percentage = hb_parnd( 2 ); + + /* run function & return value */ + hb_retl( FreeImage_AdjustBrightness(dib, percentage) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ADJUSTBRIGHTNESS", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_AdjustContrast(FIBITMAP *dib, double percentage); +HB_FUNC( FI_ADJUSTCONTRAST ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + double percentage; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + percentage = hb_parnd( 2 ); + + /* run function & return value */ + hb_retl( FreeImage_AdjustContrast(dib, percentage) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_ADJUSTCONTRAST", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_Invert(FIBITMAP *dib); +HB_FUNC( FI_INVERT ) +{ + if ( hb_pcount() == 1 && + hb_parinfo( 1 ) & HB_IT_POINTER + ) + { + FIBITMAP *dib; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + + /* run function & return value */ + hb_retl( FreeImage_Invert(dib) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_INVERT", 1, + hb_paramError( 1 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_GetHistogram(FIBITMAP *dib, DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel FI_DEFAULT(FICC_BLACK)); + +// -------------------------------------------------------------------------- + +// channel processing routines + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetChannel(FIBITMAP *dib, FREE_IMAGE_COLOR_CHANNEL channel); +HB_FUNC( FI_GETCHANNEL ) +{ + if ( hb_pcount() == 2 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + FREE_IMAGE_COLOR_CHANNEL channel; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + channel = hb_parni( 2 ); + + /* run function & return value */ + hb_retptr( FreeImage_GetChannel(dib, channel) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_GETCHANNEL", 2, + hb_paramError( 1 ), hb_paramError( 2 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_SetChannel(FIBITMAP *dib, FIBITMAP *dib8, FREE_IMAGE_COLOR_CHANNEL channel); +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetComplexChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel); +// DLL_API BOOL DLL_CALLCONV FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel); + +// -------------------------------------------------------------------------- + +// copy / paste / composite routines + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Copy(FIBITMAP *dib, int left, int top, int right, int bottom); +HB_FUNC( FI_COPY ) +{ + if ( hb_pcount() == 5 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_NUMERIC && + hb_parinfo( 3 ) & HB_IT_NUMERIC && + hb_parinfo( 4 ) & HB_IT_NUMERIC && + hb_parinfo( 5 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dib; + int left, top, right, bottom; + + /* Retrieve parameters */ + dib = hb_parptr( 1 ); + left = hb_parni( 2 ); + top = hb_parni( 3 ); + right = hb_parni( 4 ); + bottom = hb_parni( 5 ); + + /* run function & return value */ + hb_retptr( FreeImage_Copy(dib, left, top, right, bottom) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_COPY", 5, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ), + hb_paramError( 5 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API BOOL DLL_CALLCONV FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha); +HB_FUNC( FI_PASTE ) +{ + if ( hb_pcount() == 5 && + hb_parinfo( 1 ) & HB_IT_POINTER && + hb_parinfo( 2 ) & HB_IT_POINTER && + hb_parinfo( 3 ) & HB_IT_NUMERIC && + hb_parinfo( 4 ) & HB_IT_NUMERIC && + hb_parinfo( 5 ) & HB_IT_NUMERIC + ) + { + FIBITMAP *dst; + FIBITMAP *src; + int left, top, alpha; + + /* Retrieve parameters */ + dst = hb_parptr( 1 ); + src = hb_parptr( 2 ); + left = hb_parni( 3 ); + top = hb_parni( 4 ); + alpha = hb_parni( 5 ); + + /* run function & return value */ + hb_retl( FreeImage_Paste(dst, src, left, top, alpha) ); + + } + else + { + // Parameter error + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, + "FI_PASTE", 5, + hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ), + hb_paramError( 5 ) + ); + return; + } + } +} + +// -------------------------------------------------------------------------- + +// DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg FI_DEFAULT(FALSE), RGBQUAD *appBkColor FI_DEFAULT(NULL), FIBITMAP *bg FI_DEFAULT(NULL)); + +// -------------------------------------------------------------------------- + diff --git a/harbour/contrib/freeimage/freeimage.ch b/harbour/contrib/freeimage/freeimage.ch new file mode 100644 index 0000000000..6da15e3bc0 --- /dev/null +++ b/harbour/contrib/freeimage/freeimage.ch @@ -0,0 +1,337 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * FreeImage graphic library header file. + * + * Copyright 2005 Francesco Saverio Giudice + * www - http://www.xharbour.org http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#ifndef FREEIMAGE_CH +#define FREEIMAGE_CH + +/* ----------------------------------------------------------------------- */ + +#ifndef FREEIMAGE_BIGENDIAN +// Little Endian (x86 / MS Windows, Linux) : BGR(A) order +#define FI_RGBA_RED 2 +#define FI_RGBA_GREEN 1 +#define FI_RGBA_BLUE 0 +#define FI_RGBA_ALPHA 3 +#define FI_RGBA_RED_MASK 0x00FF0000 +#define FI_RGBA_GREEN_MASK 0x0000FF00 +#define FI_RGBA_BLUE_MASK 0x000000FF +#define FI_RGBA_ALPHA_MASK 0xFF000000 +#define FI_RGBA_RED_SHIFT 16 +#define FI_RGBA_GREEN_SHIFT 8 +#define FI_RGBA_BLUE_SHIFT 0 +#define FI_RGBA_ALPHA_SHIFT 24 +#else +// Big Endian (PPC / Linux, MaxOSX) : RGB(A) order +#define FI_RGBA_RED 0 +#define FI_RGBA_GREEN 1 +#define FI_RGBA_BLUE 2 +#define FI_RGBA_ALPHA 3 +#define FI_RGBA_RED_MASK 0xFF000000 +#define FI_RGBA_GREEN_MASK 0x00FF0000 +#define FI_RGBA_BLUE_MASK 0x0000FF00 +#define FI_RGBA_ALPHA_MASK 0x000000FF +#define FI_RGBA_RED_SHIFT 24 +#define FI_RGBA_GREEN_SHIFT 16 +#define FI_RGBA_BLUE_SHIFT 8 +#define FI_RGBA_ALPHA_SHIFT 0 +#endif // FREEIMAGE_BIGENDIAN + +#define FI_RGBA_RGB_MASK (FI_RGBA_RED_MASK|FI_RGBA_GREEN_MASK|FI_RGBA_BLUE_MASK) + +// The 16bit macros only include masks and shifts, since each color element is not byte aligned + +#define FI16_555_RED_MASK 0x7C00 +#define FI16_555_GREEN_MASK 0x03E0 +#define FI16_555_BLUE_MASK 0x001F +#define FI16_555_RED_SHIFT 10 +#define FI16_555_GREEN_SHIFT 5 +#define FI16_555_BLUE_SHIFT 0 +#define FI16_565_RED_MASK 0xF800 +#define FI16_565_GREEN_MASK 0x07E0 +#define FI16_565_BLUE_MASK 0x001F +#define FI16_565_RED_SHIFT 11 +#define FI16_565_GREEN_SHIFT 5 +#define FI16_565_BLUE_SHIFT 0 + +// ICC profile support ------------------------------------------------------ + +#define FIICC_DEFAULT 0x00 +#define FIICC_COLOR_IS_CMYK 0x01 + +/** I/O image format identifiers. +*/ +//FREE_IMAGE_FORMAT +#define FIF_UNKNOWN -1 +#define FIF_BMP 0 +#define FIF_ICO 1 +#define FIF_JPEG 2 +#define FIF_JNG 3 +#define FIF_KOALA 4 +#define FIF_LBM 5 +#define FIF_IFF FIF_LBM +#define FIF_MNG 6 +#define FIF_PBM 7 +#define FIF_PBMRAW 8 +#define FIF_PCD 9 +#define FIF_PCX 10 +#define FIF_PGM 11 +#define FIF_PGMRAW 12 +#define FIF_PNG 13 +#define FIF_PPM 14 +#define FIF_PPMRAW 15 +#define FIF_RAS 16 +#define FIF_TARGA 17 +#define FIF_TIFF 18 +#define FIF_WBMP 19 +#define FIF_PSD 20 +#define FIF_CUT 21 +#define FIF_XBM 22 +#define FIF_XPM 23 +#define FIF_DDS 24 +#define FIF_GIF 25 +#define FIF_HDR 26 + + +/** Image type used in FreeImage. +*/ +//FREE_IMAGE_TYPE +#define FIT_UNKNOWN 0 // unknown type +#define FIT_BITMAP 1 // standard image : 1-, 4-, 8-, 16-, 24-, 32-bit +#define FIT_UINT16 2 // array of unsigned short : unsigned 16-bit +#define FIT_INT16 3 // array of short : signed 16-bit +#define FIT_UINT32 4 // array of unsigned long : unsigned 32-bit +#define FIT_INT32 5 // array of long : signed 32-bit +#define FIT_FLOAT 6 // array of float : 32-bit IEEE floating point +#define FIT_DOUBLE 7 // array of double : 64-bit IEEE floating point +#define FIT_COMPLEX 8 // array of FICOMPLEX : 2 x 64-bit IEEE floating point +#define FIT_RGB16 9 // 48-bit RGB image : 3 x 16-bit +#define FIT_RGBA16 10 // 64-bit RGBA image : 4 x 16-bit +#define FIT_RGBF 11 // 96-bit RGB float image : 3 x 32-bit IEEE floating point +#define FIT_RGBAF 12 // 128-bit RGBA float image : 4 x 32-bit IEEE floating point + + +/** Image color type used in FreeImage. +*/ +//FREE_IMAGE_COLOR_TYPE +#define FIC_MINISWHITE 0 // min value is white +#define FIC_MINISBLACK 1 // min value is black +#define FIC_RGB 2 // RGB color model +#define FIC_PALETTE 3 // color map indexed +#define FIC_RGBALPHA 4 // RGB color model with alpha channel +#define FIC_CMYK 5 // CMYK color model + + +/** Color quantization algorithms. +Constants used in FreeImage_ColorQuantize. +*/ +//FREE_IMAGE_QUANTIZE +#define FIQ_WUQUANT 0 // Xiaolin Wu color quantization algorithm +#define FIQ_NNQUANT 1 // NeuQuant neural-net quantization algorithm by Anthony Dekker + + +/** Dithering algorithms. +Constants used in FreeImage_Dither. +*/ +//FREE_IMAGE_DITHER +#define FID_FS 0 // Floyd & Steinberg error diffusion +#define FID_BAYER4x4 1 // Bayer ordered dispersed dot dithering (order 2 dithering matrix) +#define FID_BAYER8x8 2 // Bayer ordered dispersed dot dithering (order 3 dithering matrix) +#define FID_CLUSTER6x6 3 // Ordered clustered dot dithering (order 3 - 6x6 matrix) +#define FID_CLUSTER8x8 4 // Ordered clustered dot dithering (order 4 - 8x8 matrix) +#define FID_CLUSTER16x16 5 // Ordered clustered dot dithering (order 8 - 16x16 matrix) + + +/** Lossless JPEG transformations +Constants used in FreeImage_JPEGTransform +*/ +//FREE_IMAGE_JPEG_OPERATION +#define FIJPEG_OP_NONE 0 // no transformation +#define FIJPEG_OP_FLIP_H 1 // horizontal flip +#define FIJPEG_OP_FLIP_V 2 // vertical flip +#define FIJPEG_OP_TRANSPOSE 3 // transpose across UL-to-LR axis +#define FIJPEG_OP_TRANSVERSE 4 // transpose across UR-to-LL axis +#define FIJPEG_OP_ROTATE_90 5 // 90-degree clockwise rotation +#define FIJPEG_OP_ROTATE_180 6 // 180-degree rotation +#define FIJPEG_OP_ROTATE_270 7 // 270-degree clockwise (or 90 ccw) + + +/** Tone mapping operators. +Constants used in FreeImage_ToneMapping. +*/ +//FREE_IMAGE_TMO +#define FITMO_DRAGO03 0 // Adaptive logarithmic mapping (F. Drago, 2003) +#define FITMO_REINHARD05 1 // Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005) + + +/** Upsampling / downsampling filters. +Constants used in FreeImage_Rescale. +*/ +//FREE_IMAGE_FILTER +#define FILTER_BOX 0 // Box, pulse, Fourier window, 1st order (constant) b-spline +#define FILTER_BICUBIC 1 // Mitchell & Netravali's two-param cubic filter +#define FILTER_BILINEAR 2 // Bilinear filter +#define FILTER_BSPLINE 3 // 4th order (cubic) b-spline +#define FILTER_CATMULLROM 4 // Catmull-Rom spline, Overhauser spline +#define FILTER_LANCZOS3 5 // Lanczos3 filter + + +/** Color channels. +Constants used in color manipulation routines. +*/ +//FREE_IMAGE_COLOR_CHANNEL +#define FICC_RGB 0 // Use red, green and blue channels +#define FICC_RED 1 // Use red channel +#define FICC_GREEN 2 // Use green channel +#define FICC_BLUE 3 // Use blue channel +#define FICC_ALPHA 4 // Use alpha channel +#define FICC_BLACK 5 // Use black channel +#define FICC_REAL 6 // Complex images: use real part +#define FICC_IMAG 7 // Complex images: use imaginary part +#define FICC_MAG 8 // Complex images: use magnitude +#define FICC_PHASE 9 // Complex images: use phase + +// Metadata support --------------------------------------------------------- + +/** + Tag data type information (based on TIFF specifications) + + Note: RATIONALs are the ratio of two 32-bit integer values. +*/ +//FREE_IMAGE_MDTYPE +#define FIDT_NOTYPE 0 // placeholder +#define FIDT_BYTE 1 // 8-bit unsigned integer +#define FIDT_ASCII 2 // 8-bit bytes w/ last byte null +#define FIDT_SHORT 3 // 16-bit unsigned integer +#define FIDT_LONG 4 // 32-bit unsigned integer +#define FIDT_RATIONAL 5 // 64-bit unsigned fraction +#define FIDT_SBYTE 6 // 8-bit signed integer +#define FIDT_UNDEFINED 7 // 8-bit untyped data +#define FIDT_SSHORT 8 // 16-bit signed integer +#define FIDT_SLONG 9 // 32-bit signed integer +#define FIDT_SRATIONAL 10 // 64-bit signed fraction +#define FIDT_FLOAT 11 // 32-bit IEEE floating point +#define FIDT_DOUBLE 12 // 64-bit IEEE floating point +#define FIDT_IFD 13 // 32-bit unsigned integer (offset) +#define FIDT_PALETTE 14 // 32-bit RGBQUAD + + +/** + Metadata models supported by FreeImage +*/ +//FREE_IMAGE_MDMODEL +#define FIMD_NODATA -1 +#define FIMD_COMMENTS 0 // single comment or keywords +#define FIMD_EXIF_MAIN 1 // Exif-TIFF metadata +#define FIMD_EXIF_EXIF 2 // Exif-specific metadata +#define FIMD_EXIF_GPS 3 // Exif GPS metadata +#define FIMD_EXIF_MAKERNOTE 4 // Exif maker note metadata +#define FIMD_EXIF_INTEROP 5 // Exif interoperability metadata +#define FIMD_IPTC 6 // IPTC/NAA metadata +#define FIMD_XMP 7 // Abobe XMP metadata +#define FIMD_GEOTIFF 8 // GeoTIFF metadata +#define FIMD_ANIMATION 9 // Animation metadata +#define FIMD_CUSTOM 10 // Used to attach other metadata types to a dib + +// Load / Save flag constants ----------------------------------------------- + +#define BMP_DEFAULT 0 +#define BMP_SAVE_RLE 1 +#define CUT_DEFAULT 0 +#define DDS_DEFAULT 0 +#define GIF_DEFAULT 0 +#define GIF_LOAD256 1 // Load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color +#define GIF_PLAYBACK 2 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading +#define HDR_DEFAULT 0 +#define ICO_DEFAULT 0 +#define ICO_MAKEALPHA 1 // convert to 32bpp and create an alpha channel from the AND-mask when loading +#define IFF_DEFAULT 0 +#define JPEG_DEFAULT 0 +#define JPEG_FAST 1 +#define JPEG_ACCURATE 2 +#define JPEG_QUALITYSUPERB 0x80 +#define JPEG_QUALITYGOOD 0x100 +#define JPEG_QUALITYNORMAL 0x200 +#define JPEG_QUALITYAVERAGE 0x400 +#define JPEG_QUALITYBAD 0x800 +#define JPEG_CMYK 0x1000 // load separated CMYK "as is" (use | to combine with other flags) +#define KOALA_DEFAULT 0 +#define LBM_DEFAULT 0 +#define MNG_DEFAULT 0 +#define PCD_DEFAULT 0 +#define PCD_BASE 1 // load the bitmap sized 768 x 512 +#define PCD_BASEDIV4 2 // load the bitmap sized 384 x 256 +#define PCD_BASEDIV16 3 // load the bitmap sized 192 x 128 +#define PCX_DEFAULT 0 +#define PNG_DEFAULT 0 +#define PNG_IGNOREGAMMA 1 // avoid gamma correction +#define PNM_DEFAULT 0 +#define PNM_SAVE_RAW 0 // If set the writer saves in RAW format (i.e. P4, P5 or P6) +#define PNM_SAVE_ASCII 1 // If set the writer saves in ASCII format (i.e. P1, P2 or P3) +#define PSD_DEFAULT 0 +#define RAS_DEFAULT 0 +#define TARGA_DEFAULT 0 +#define TARGA_LOAD_RGB888 1 // If set the loader converts RGB555 and ARGB8888 -> RGB888. +#define TIFF_DEFAULT 0 +#define TIFF_CMYK 0x0001 // reads/stores tags for separated CMYK (use | to combine with compression flags) +#define TIFF_PACKBITS 0x0100 // save using PACKBITS compression +#define TIFF_DEFLATE 0x0200 // save using DEFLATE compression (a.k.a. ZLIB compression) +#define TIFF_ADOBE_DEFLATE 0x0400 // save using ADOBE DEFLATE compression +#define TIFF_NONE 0x0800 // save without any compression +#define TIFF_CCITTFAX3 0x1000 // save using CCITT Group 3 fax encoding +#define TIFF_CCITTFAX4 0x2000 // save using CCITT Group 4 fax encoding +#define TIFF_LZW 0x4000 // save using LZW compression +#define TIFF_JPEG 0x8000 // save using JPEG compression +#define WBMP_DEFAULT 0 +#define XBM_DEFAULT 0 +#define XPM_DEFAULT 0 + +#endif // FREEIMAGE_CH diff --git a/harbour/contrib/freeimage/make_b32.bat b/harbour/contrib/freeimage/make_b32.bat new file mode 100644 index 0000000000..65f41f74b8 --- /dev/null +++ b/harbour/contrib/freeimage/make_b32.bat @@ -0,0 +1,79 @@ +@echo off +rem +rem $Id$ +rem + +rem --------------------------------------------------------------- +rem IMPORTANT: You'll need Freeimage headers and binary from here: +rem http://freeimage.sourceforge.net/download.html +rem and this envvar to be set to successfully build this library: +rem set FREEIMAGE_DIR=C:\FreeImage +rem --------------------------------------------------------------- + +rem --------------------------------------------------------------- +rem This is a generic template file, if it doesn't fit your own needs +rem please DON'T MODIFY IT. +rem +rem Instead, make a local copy and modify that one, or make a call to +rem this batch file from your customized one. [vszakats] +rem +rem Set any of the below settings to customize your build process: +rem set HB_MAKE_PROGRAM= +rem set HB_MAKE_FLAGS= +rem --------------------------------------------------------------- + +if "%HB_DLL_DIR%" == "" set HB_DLL_DIR=%SystemRoot%\system32 +if "%HB_CC_NAME%" == "" set HB_CC_NAME=b32 +if "%HB_MAKE_PROGRAM%" == "" set HB_MAKE_PROGRAM=make.exe +set HB_MAKEFILE=..\mtpl_%HB_CC_NAME%.mak + +set C_USR=%C_USR% -I%FREEIMAGE_DIR%\source -DHB_OS_WIN_32_USED + +rem --------------------------------------------------------------- + +rem Save the user value, force silent file overwrite with COPY +rem (not all Windows versions support the COPY /Y flag) +set HB_ORGENV_COPYCMD=%COPYCMD% +set COPYCMD=/Y + +rem --------------------------------------------------------------- + +if "%1" == "clean" goto CLEAN +if "%1" == "CLEAN" goto CLEAN + +if "%1" == "install" goto INSTALL +if "%1" == "INSTALL" goto INSTALL + +:BUILD + + implib ..\..\lib\%HB_CC_NAME%\FreeImage.lib %FREEIMAGE_DIR%\Dist\FreeImage.dll + + %HB_MAKE_PROGRAM% %HB_MAKE_FLAGS% -f %HB_MAKEFILE% %1 %2 %3 > make_%HB_CC_NAME%.log + if errorlevel 1 notepad make_%HB_CC_NAME%.log + goto EXIT + +:CLEAN + + %HB_MAKE_PROGRAM% %HB_MAKE_FLAGS% -f %HB_MAKEFILE% CLEAN > make_%HB_CC_NAME%.log + if exist make_%HB_CC_NAME%.log del make_%HB_CC_NAME%.log > nul + if exist inst_%HB_CC_NAME%.log del inst_%HB_CC_NAME%.log > nul + goto EXIT + +:INSTALL + + set _HB_INSTALL_PREFIX=%HB_INSTALL_PREFIX% + if "%_HB_INSTALL_PREFIX%" == "" set _HB_INSTALL_PREFIX=..\.. + set _HB_LIB_INSTALL=%HB_LIB_INSTALL% + if "%_HB_LIB_INSTALL%" == "" set _HB_LIB_INSTALL=%_HB_INSTALL_PREFIX%\lib + + copy ..\..\lib\%HB_CC_NAME%\FreeImage.lib %_HB_LIB_INSTALL% + + %HB_MAKE_PROGRAM% %HB_MAKE_FLAGS% -f %HB_MAKEFILE% INSTALL > nul + goto EXIT + +:EXIT + +rem --------------------------------------------------------------- + +rem Restore user value +set COPYCMD=%HB_ORGENV_COPYCMD% diff --git a/harbour/contrib/freeimage/make_vc.bat b/harbour/contrib/freeimage/make_vc.bat new file mode 100644 index 0000000000..52a587b165 --- /dev/null +++ b/harbour/contrib/freeimage/make_vc.bat @@ -0,0 +1,95 @@ +@echo off +rem +rem $Id$ +rem + +rem --------------------------------------------------------------- +rem IMPORTANT: You'll need Freeimage headers and binary from here: +rem http://freeimage.sourceforge.net/download.html +rem and this envvar to be set to successfully build this library: +rem set FREEIMAGE_DIR=C:\FreeImage +rem --------------------------------------------------------------- + +rem --------------------------------------------------------------- +rem This is a generic template file, if it doesn't fit your own needs +rem please DON'T MODIFY IT. +rem +rem Instead, make a local copy and modify that one, or make a call to +rem this batch file from your customized one. [vszakats] +rem +rem Set any of the below settings to customize your build process: +rem set HB_MAKE_PROGRAM= +rem set HB_MAKE_FLAGS= +rem --------------------------------------------------------------- + +if "%HB_DLL_DIR%" == "" set HB_DLL_DIR=%SystemRoot%\system32 +if "%HB_CC_NAME%" == "" set HB_CC_NAME=vc +if "%HB_MAKE_PROGRAM%" == "" set HB_MAKE_PROGRAM=nmake.exe +set HB_MAKEFILE=..\mtpl_%HB_CC_NAME%.mak + +set C_USR=%C_USR% -I%FREEIMAGE_DIR%\source -DHB_OS_WIN_32_USED + +rem --------------------------------------------------------------- + +rem Save the user value, force silent file overwrite with COPY +rem (not all Windows versions support the COPY /Y flag) +set HB_ORGENV_COPYCMD=%COPYCMD% +set COPYCMD=/Y + +rem --------------------------------------------------------------- + +if "%1" == "clean" goto CLEAN +if "%1" == "CLEAN" goto CLEAN + +if "%1" == "install" goto INSTALL +if "%1" == "INSTALL" goto INSTALL + +:BUILD + + rem --------------------------------------------------------------- + rem This .dll to .lib conversion needs GNU sed.exe in the path + rem --------------------------------------------------------------- + echo./[ \t]*ordinal hint/,/^^[ \t]*Summary/{> _temp.sed + echo. /^^[ \t]\+[0-9]\+/{>> _temp.sed + echo. s/^^[ \t]\+[0-9]\+[ \t]\+[0-9A-Fa-f]\+[ \t]\+[0-9A-Fa-f]\+[ \t]\+\(.*\)/\1/p>> _temp.sed + echo. }>> _temp.sed + echo.}>> _temp.sed + DUMPBIN /EXPORTS %FREEIMAGE_DIR%\Dist\FreeImage.dll > _dump.tmp + echo.LIBRARY %FREEIMAGE_DIR%\Dist\FreeImage.dll > _temp.def + echo.EXPORTS >> _temp.def + sed -nf _temp.sed < _dump.tmp >> _temp.def + LIB /MACHINE:X86 /DEF:_temp.def /OUT:..\..\lib\%HB_CC_NAME%\FreeImage.lib + del _dump.tmp + del _temp.def + del _temp.sed + rem --------------------------------------------------------------- + + %HB_MAKE_PROGRAM% %HB_MAKE_FLAGS% -f %HB_MAKEFILE% %1 %2 %3 > make_%HB_CC_NAME%.log + if errorlevel 1 notepad make_%HB_CC_NAME%.log + goto EXIT + +:CLEAN + + %HB_MAKE_PROGRAM% %HB_MAKE_FLAGS% -f %HB_MAKEFILE% CLEAN > make_%HB_CC_NAME%.log + if exist make_%HB_CC_NAME%.log del make_%HB_CC_NAME%.log > nul + if exist inst_%HB_CC_NAME%.log del inst_%HB_CC_NAME%.log > nul + goto EXIT + +:INSTALL + + set _HB_INSTALL_PREFIX=%HB_INSTALL_PREFIX% + if "%_HB_INSTALL_PREFIX%" == "" set _HB_INSTALL_PREFIX=..\.. + set _HB_LIB_INSTALL=%HB_LIB_INSTALL% + if "%_HB_LIB_INSTALL%" == "" set _HB_LIB_INSTALL=%_HB_INSTALL_PREFIX%\lib + + copy ..\..\lib\%HB_CC_NAME%\FreeImage.lib %_HB_LIB_INSTALL% + + %HB_MAKE_PROGRAM% %HB_MAKE_FLAGS% -f %HB_MAKEFILE% INSTALL > nul + goto EXIT + +:EXIT + +rem --------------------------------------------------------------- + +rem Restore user value +set COPYCMD=%HB_ORGENV_COPYCMD% diff --git a/harbour/contrib/freeimage/readme.txt b/harbour/contrib/freeimage/readme.txt new file mode 100644 index 0000000000..01de1a7b96 --- /dev/null +++ b/harbour/contrib/freeimage/readme.txt @@ -0,0 +1,58 @@ +/* + * $Id$ + */ + +/* + * The following parts are Copyright of the individual authors. + * www - http://www.xharbour.org http://www.harbour-project.org + * + * Copyright 2005 Francesco Saverio Giudice + * README file explaining howto compile FreeImage library + * + * See doc/license.txt for licensing terms. + * + */ + +FreeImage Library is a porting to xHarbour of famous FreeImage Project library. + +Actually based on FreeImage version 3.8.0 +FreeImage Project's web site is http://freeimage.sourceforge.net/ + +COMPILING +========= + +Actually platforms supported are: +- Win32 / BCC32 +- GNU systems / GCC + +to build library on Win32 with BCC use: +make_b32.bat + +on GNU system use: +make install +WARNING: not actually tested + + ** requirements: to build FreeImage library: gcc-c++, libstdc++-devel + +DOCUMENTATION +============= + +Look at doc folder for help files. +Last FreeImage pdf manual is downloadable from http://freeimage.sourceforge.net/download.html + +SAMPLES +======= + +For samples look at tests dir. +fitest.prg is an API test application. + +NOTES +===== + +WARNING: if you are using Windows platform, download the + FreeImage.dll in tests before use it. + +At this time (28/10/2005 CET) it builds on Windows with last CVS. +Not tested on GNU system, but it have to run correctly. + + diff --git a/harbour/contrib/freeimage/test/bld_b32.bat b/harbour/contrib/freeimage/test/bld_b32.bat new file mode 100644 index 0000000000..830467e7d1 --- /dev/null +++ b/harbour/contrib/freeimage/test/bld_b32.bat @@ -0,0 +1,80 @@ +@echo off +rem +rem $Id$ +rem + +if A%1 == A GOTO :SYNTAX +if NOT EXIST %1.prg GOTO :NOEXIST + +ECHO Build: Compiling... + +set hdir=..\..\.. + +%hdir%\bin\harbour %1 /w /n /i..\include;%hdir%\include %2 %3 > bld_b32.log +type bld_b32.log +IF ERRORLEVEL 1 PAUSE +IF ERRORLEVEL 1 GOTO EXIT + +echo -O2 -e%1.exe -I%hdir%\include %1.c > bld_b32.mak +bcc32 -M -c @bld_b32.mak +:ENDCOMPILE + +echo c0w32.obj + > bld_b32.mak +echo %1.obj, + >> bld_b32.mak +echo %1.exe, + >> bld_b32.mak +echo %1.map, + >> bld_b32.mak +echo %hdir%\lib\rtl.lib + >> bld_b32.mak +echo %hdir%\lib\vm.lib + >> bld_b32.mak +echo %hdir%\lib\gtwin.lib + >> bld_b32.mak +echo %hdir%\lib\lang.lib + >> bld_b32.mak +echo %hdir%\lib\macro.lib + >> bld_b32.mak +echo %hdir%\lib\rdd.lib + >> bld_b32.mak +echo %hdir%\lib\dbfntx.lib + >> bld_b32.mak +echo %hdir%\lib\dbfcdx.lib + >> bld_b32.mak +echo %hdir%\lib\debug.lib + >> bld_b32.mak +echo %hdir%\lib\common.lib + >> bld_b32.mak +echo %hdir%\lib\pp.lib + >> bld_b32.mak +echo %hdir%\lib\hbsix.lib + >> bld_b32.mak +echo %hdir%\lib\dbffpt.lib + >> bld_b32.mak +echo %hdir%\lib\fi_lib.lib + >> bld_b32.mak +echo %hdir%\lib\freeimage.lib + >> bld_b32.mak + +rem Uncomment these two lines to use Advantage RDD +rem echo %hdir%\lib\rddads.lib + >> bld_b32.mak +rem echo %hdir%\lib\ace32.lib + >> bld_b32.mak + +echo cw32.lib + >> bld_b32.mak +echo import32.lib, >> bld_b32.mak + +ECHO Build: Linking... +rem Use these flags to avoid the console window creation +rem ilink32 -Gn -aa -Tpe -s @bld_b32.mak +ilink32 -Gn -Tpe -s @bld_b32.mak + +rem delete temporary files +del %1.c +del %1.obj +if exist %1.map del %1.map +if exist %1.tds del %1.tds +del bld_b32.mak +del bld_b32.log + +IF ERRORLEVEL 1 GOTO LINKERROR +ECHO Build: Done. +%1 +GOTO EXIT +ECHO + +:LINKERROR +rem if exist meminfo.txt notepad meminfo.txt +rem PAUSE * Linking errors * +GOTO EXIT + +:SYNTAX +ECHO SYNTAX: bld_b32 [Program] {-- Don't specify .prg extension +GOTO EXIT + +:NOEXIST +ECHO Build: The specified %1.prg does not exist + +:EXIT diff --git a/harbour/contrib/freeimage/test/fitest.prg b/harbour/contrib/freeimage/test/fitest.prg new file mode 100644 index 0000000000..97657fe32e --- /dev/null +++ b/harbour/contrib/freeimage/test/fitest.prg @@ -0,0 +1,242 @@ +/* + * $Id$ + */ + +/* + * Copyright 2005 Francesco Saverio Giudice + * + * FreeImage API test file + */ + +#include "FreeImage.ch" +#include "common.ch" + +#define IMAGES_IN "" +#define IMAGES_OUT "images_out/" + +PROCEDURE Main() + + LOCAL im, clone, rotated, rotatedEx, rescale, im2, im3 + LOCAL centerX, centerY, width, height, appo + LOCAL bmpinfoheader + LOCAL bmpinfo + LOCAL bkcolor + LOCAL iccprofile + LOCAL x + + //? "Press Alt-D + Enter to activate debug" + //AltD( .T. ) + //Inkey(0) + altd() + // Check output directory + IF !hb_DirExists( IMAGES_OUT ) +#ifdef HB_COMPAT_C53 + MakeDir( IMAGES_OUT ) +#endif + ENDIF + + ? "Initialise" + fi_Initialise() + //---------------------------// + + ? "Set Error Message:", fi_SetOutPutMessage( fi_Error() ) + //? "Set Error Message:", fi_SetOutPutMessage( NIL ) + + ? "Version :", fi_GetVersion() + ? "Copyright :", fi_GetCopyrightMessage() + ? "File type :", fi_GetFileType( IMAGES_IN + "sample1.jpg" ) + ? "Load JPEG" + im := fi_Load( FIF_JPEG, IMAGES_IN + "sample1.jpg", JPEG_DEFAULT ) + + ? "Clone image" + clone := fi_Clone( im ) + + ? "Pointer :", ValToPrg( im ) + + ? "Image Type :", fi_GetImageType( im ) + ? "Color Used :", fi_GetColorsUsed( im ) + ? "Pixel size :", fi_GetBPP( im ) + ? "Width :", fi_GetWidth( im ) + ? "Height :", fi_GetHeight( im ) + ? "Byte Size :", fi_GetLine( im ) + ? "Pitch :", fi_GetPitch( im ) + ? "DIB Size :", fi_GetDIBSize( im ) + ? "Dots per Meter X :", fi_GetDotsPerMeterX( im ) + ? "Dots per Meter Y :", fi_GetDotsPerMeterY( im ) + ? "Color Type :", fi_GetColorType( im ) + ? "Red Mask :", fi_GetRedMask( im ) + ? "Green Mask :", fi_GetGreenMask( im ) + ? "Blue Mask :", fi_GetBlueMask( im ) + ? "Transp. Count :", fi_GetTransparencyCount( im ) + ? "Is Transparent ? :", fi_IsTransparent( im ) + ? + ? "Save BMP ? :", fi_Save( FIF_BMP , im, IMAGES_OUT + "sample1.bmp", BMP_DEFAULT ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im, IMAGES_OUT + "sample1.jpg", JPEG_DEFAULT ) + ? "Save PNG ? :", fi_Save( FIF_PNG , im, IMAGES_OUT + "sample1.png", PNG_DEFAULT ) + + ? "Save TIFF ? :", fi_Save( FIF_TIFF, clone, IMAGES_OUT + "sample1.tif", TIFF_DEFAULT ) + ? "Flip Horizontal ?:", fi_FlipHorizontal( clone ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, clone, IMAGES_OUT + "horizontal.jpg", JPEG_DEFAULT ) + ? "Flip Vertical ? :", fi_FlipVertical( clone ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, clone, IMAGES_OUT + "vertical.jpg", JPEG_DEFAULT ) + + ? "Rotate Classic :", ValToPrg( rotated := fi_RotateClassic( clone, 90 ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, rotated, IMAGES_OUT + "rotate.jpg", JPEG_DEFAULT ) + fi_Unload( rotated ) + + centerx := fi_GetWidth( clone ) / 2 + centery := fi_GetHeight( clone ) / 2 + ? "Rotate Ex :", ValToPrg( rotatedEx := fi_RotateEx( clone, 15, 0, 0, centerx, centery, TRUE ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, rotatedEx, IMAGES_OUT + "rotateEx.jpg", JPEG_DEFAULT ) + fi_Unload( rotatedEx ) + + width := fi_GetWidth( im ) + height := fi_GetHeight( im ) + + ? "Rescale :", ValToPrg( rescale := fi_Rescale( im, width / 2, height / 2, FILTER_BICUBIC ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, rescale, IMAGES_OUT + "rescale.jpg", JPEG_DEFAULT ) + fi_Unload( rescale ) + + im2 := fi_Clone( im ) + ? "Adjust Gamma ? :", fi_AdjustGamma( im2, 3.0 ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "adjgamma.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + im2 := fi_Clone( im ) + ? "Adjust Brightness:", fi_AdjustBrightness( im2, -30 ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "adjbright.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + im2 := fi_Clone( im ) + ? "Adjust Contrast ?:", fi_AdjustContrast( im2, -30 ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "adjcontrast.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + im2 := fi_Clone( im ) + ? "Invert ? :", fi_Invert( im2 ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "invert.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + ? "Red Channel :", ValToPrg( im2 := fi_GetChannel( im, FICC_RED ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "red.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + ? "Green Channel :", ValToPrg( im2 := fi_GetChannel( im, FICC_GREEN ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "green.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + ? "Blue Channel :", ValToPrg( im2 := fi_GetChannel( im, FICC_BLUE ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "blue.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + + ? "Copy :", ValToPrg( im2 := fi_Copy( im, 300, 100, 800, 200 ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im2, IMAGES_OUT + "copy.jpg", JPEG_DEFAULT ) + + im3 := fi_Clone( im ) + ? "Paste ? :", fi_Paste( im3, im2, 10, 10, 70 ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im3, IMAGES_OUT + "paste.jpg", JPEG_DEFAULT ) + fi_Unload( im2 ) + fi_Unload( im3 ) + + ? "Allocate Bitmap :", ValToPrg( im3 := fi_AllocateT( FIT_BITMAP, 320, 200, 32 ) ) + ? "Save JPG ? :", fi_Save( FIF_JPEG, im3, IMAGES_OUT + "allocate.jpg", JPEG_DEFAULT ) + fi_Unload( im3 ) + + ? "Create ERROR :" + ? "Save GIF ? :", fi_Save( FIF_GIF, im, IMAGES_OUT + "wrong.gif", 0 ) + + //? ValToPrg( fi_GetInfoHeader( im ) ) + //bmpinfoheader:Buffer( fi_GetInfoHeader( im ), TRUE ) + //bmpinfoheader:Pointer( fi_GetInfoHeader( im ) ) + //? "Header :", ValToPrg( bmpinfoheader ) + //? bmpinfoheader:SayMembers(" ", .t., .t.) + + //bmpinfo:Pointer( fi_GetInfo( im ) ) + ? "Info :", ValToPrg( bmpinfo ) + //? bmpinfo:SayMembers(" ", .t., .t.) + ? "-----------------------------------------------------" + //? ValType( bmpinfo:Devalue() ) + //Tracelog( "bmpinfoheader", ValToPrg( bmpinfoheader ), ; + // bmpinfoheader:SayMembers(, .t.), bmpinfoheader:Value(), bmpinfoheader:DeValue(), hb_dumpvar( bmpinfoheader:Array() ), hb_dumpvar( bmpinfoheader:acMembers ) ) + + //appo := bkcolor:Value() + //? bkcolor:Pointer( fi_GetBackgroundColor( im ) ) + //? fi_GetBackgroundColor( im, @bkcolor:Value() ) + //bkcolor:Buffer( appo ) + //? bkcolor:SayMembers(" ", .t., .t.) + + //bkcolor:rgbBlue := 205 + //? fi_SetBackgroundColor( im, hb_String2Pointer( bkcolor:Value() ) ) + Tracelog("linha 168") + //? fi_SetBackgroundColor( im, bkcolor:Value() ) + Tracelog("linha 170") + //? bkcolor:SayMembers(" ", .t., .t.) +Tracelog("linha 162") +// ? bkcolor:Pointer( fi_GetBackgroundColor( im ) ) + //? fi_GetBackgroundColor( im, @bkcolor:Value() ) + //bkcolor:Buffer( appo ) +Tracelog("linha 176") + //? bkcolor:SayMembers(" ", .t., .t.) + +Tracelog("linha 179") + //iccprofile:Pointer( fi_GetICCProfile( im ) ) + Tracelog("linha 181") + //? "Header :", ValToPrg( iccprofile ) + Tracelog("linha 183") + //? iccprofile:SayMembers(" ", .t., .t.) + + //bmpinfoheader:Reset() + //appo := NIL + //bmpinfoheader := NIL + //hb_GCAll( .T. ) + + ? "Unload images from memory" + fi_Unload( im ) + fi_Unload( clone ) + + + //---------------------------// + ? "DeInitialise" + fi_Deinitialise() + + ? + ? "Look at " + IMAGES_OUT + " folder for output images" + ? + +RETURN + +PROCEDURE fi_Error( cFormat, cMessage ) + ? "ERROR!..." + ? "Format : ", cFormat + ? "Message : ", cMessage +RETURN + +PROCEDURE TraceLog( c ) + HB_SYMBOL_UNUSED( c ) + RETURN + +FUNCTION ValToPrg( xValue ) + LOCAL cType := ValType( xValue ) + + DO CASE + CASE cType == "C" + + xValue := StrTran( xValue, Chr(0), '"+Chr(0)+"' ) + xValue := StrTran( xValue, Chr(9), '"+Chr(9)+"' ) + xValue := StrTran( xValue, Chr(10), '"+Chr(10)+"' ) + xValue := StrTran( xValue, Chr(13), '"+Chr(13)+"' ) + xValue := StrTran( xValue, Chr(26), '"+Chr(26)+"' ) + + RETURN '"' + xValue + '"' + + CASE cType == "N" ; RETURN LTrim( Str( xValue ) ) + CASE cType == "D" ; RETURN 'HB_SToD("' + DToS( xValue ) + '")' + CASE cType == "L" ; RETURN iif( xValue, ".T.", ".F." ) + CASE cType == "O" ; RETURN xValue:className() + " Object" + CASE cType == "U" ; RETURN "NIL" + CASE cType == "B" ; RETURN '{||...}' + CASE cType == "A" ; RETURN '{.[' + LTrim( Str( Len( xValue ) ) ) + '].}' + CASE cType == "M" ; RETURN 'M:"' + xValue + '"' + ENDCASE + + RETURN "" diff --git a/harbour/contrib/freeimage/test/fsg.jpg b/harbour/contrib/freeimage/test/fsg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..767bf1b3315561006992e491cdd7b0bad2e67347 GIT binary patch literal 1706 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 z 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