From 4f6c83bb64207f45af180cd211a55e2c479a8fc7 Mon Sep 17 00:00:00 2001 From: "David G. Holm" Date: Wed, 11 Aug 1999 15:56:57 +0000 Subject: [PATCH] See ChangeLog entry 19990811-11:35 EDT David G. Holm --- harbour/ChangeLog | 23 +++++ harbour/doc/gmake.txt | 14 ++- harbour/source/rtl/console.c | 17 ++-- harbour/source/rtl/gt/gtdos.c | 114 ++++++++++++++++++---- harbour/source/rtl/gt/gtos2.c | 2 +- harbour/source/rtl/setkey.prg | 151 +++++++++++++++++++++++++++--- harbour/tests/working/Makefile | 1 + harbour/tests/working/setkeys.prg | 84 +++++++++++++++++ 8 files changed, 369 insertions(+), 37 deletions(-) create mode 100644 harbour/tests/working/setkeys.prg diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 0607771b50..2e49eb1f17 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,26 @@ +19990811-11:35 EDT David G. Holm + * doc/gmake.txt + + Added a new section under 'NOTES' discussing how to build only + parts of Harbour, with examples for Harbour only and tests only + and how to build a single test file using the DOS build.bat file. + * source/rtl/console.c + ! Corrected #ifdef blocks for unistd.h and io.h. + ! Added code to remove newline in Unix compatible ACCEPT() code, + per Georg Lehner . + * source/rtl/setkey.prg + * New version from April White . + * source/rtl/gt/gtdos.c + + Added DJGPP compatible GTAPI handling, but not sure how to deal + with dispbegin()/dispend(). Need to add cursor handling. + * source/rtl/gt/gtos2.c + ! Changed DWORD to ULONG. + * tests/working/Makefile + ! Added new setkey test program (as BAD, because no GETACTIVE()). + + tests/working/setkey.prg + + New test program from April White . + Note: Needs a working get system and needs SetKeyCheck() + integrated into the appropriate Harbour input functions. + 19990810-00:55 EDT Paul Tucker * source/rtl/gtapi.c source/rtl/gt/gtwin/c source/rtl/gt/gt_tpl.c * minor formatting changes diff --git a/harbour/doc/gmake.txt b/harbour/doc/gmake.txt index 69aa7defe9..c6016c1275 100644 --- a/harbour/doc/gmake.txt +++ b/harbour/doc/gmake.txt @@ -207,4 +207,16 @@ Harbour source code. The -r option isn't strictly necessary, but it does signficantly reduce the number of rules that make has to evaluate otherwise, which may give -a big performance boost on a slow system. \ No newline at end of file +a performance boost on a slow system. + + +To rebuild only a part of Harbour, go to the appropriate source directory +and then run 'make -r'. For example, to rebuild all of Harbour, but not +the test programs, change to the 'source' directory. To rebuild only the +test programs, change to the 'test' directory. + + +If you are using a DOS-based operating system, then you can build any +program in tests/working by using the build batch file. For example, +'build scroll' will rebuild the scroll.prg module. This can also be used +for modules that aren't in the Makefile. diff --git a/harbour/source/rtl/console.c b/harbour/source/rtl/console.c index 3e8d3b378d..ce29ffbe0e 100644 --- a/harbour/source/rtl/console.c +++ b/harbour/source/rtl/console.c @@ -54,14 +54,14 @@ #include "set.h" #include "inkey.h" -#if defined(__GNUC__) && ! defined(__DJGPP__) +#if defined(__GNUC__) #include + #if defined(__DJGPP__) || defined(__CYGWIN__) || defined(HARBOUR_GCC_OS2) + #include + #endif #else #include #endif -#if defined(__CYGWIN__) - #include -#endif #include #include "gtapi.h" /* HARBOUR_USE_GTAPI is checked inside gtapi.h, so that we can always get the border styles */ @@ -1076,8 +1076,13 @@ HARBOUR HB___ACCEPT( void ) /* Internal Clipper function used in ACCEPT command } #ifdef OS_UNIX_COMPATIBLE /* Read the data using fgets(), because hb_inkeyPoll() doesn't support - Unix compatible operating systems yet. */ - fgets( szResult, ACCEPT_BUFFER_LEN, stdin ); + Unix compatible operating systems yet. */ + szResult[0] = `\0`; /* start with something defined */ + if (fgets( szResult, ACCEPT_BUFFER_LEN, stdin )) + { + strtok(szResult, "\n"); /* strip off the trailing newline + if it exists */ + } #else len = 0; input = 0; diff --git a/harbour/source/rtl/gt/gtdos.c b/harbour/source/rtl/gt/gtdos.c index 7951bb0c0d..a7fc8cd47f 100644 --- a/harbour/source/rtl/gt/gtdos.c +++ b/harbour/source/rtl/gt/gtdos.c @@ -17,19 +17,22 @@ #if defined(__POWERC) || (defined(__TURBOC__) && !defined(__BORLANDC__)) || \ (defined(__ZTC__) && !defined(__SC__)) -#define FAR far + #define FAR far +#elif (defined(__MSDOS__) || defined(MSDOS) || defined(DOS)) && !defined(__DJGPP__) + #define FAR _far #else -#if defined(__MSDOS__) || defined(MSDOS) || defined(DOS) -#define FAR _far -#else -#define FAR -#endif + #define FAR #endif +#ifdef __DJGPP__ + #include + #include +#else #ifndef MK_FP #define MK_FP(seg,off) \ ((void FAR *)(((unsigned long)(seg) << 16)|(unsigned)(off))) #endif +#endif static void hb_gt_xGetXY(char cRow, char cCol, char *attr, char *ch); static void hb_gt_xPutch(char cRow, char cCol, char attr, char ch); @@ -39,16 +42,22 @@ static void hb_gt_SetCursorSize(char start, char end); static void hb_gt_GetCursorSize(char *start, char *end); #if defined(__WATCOMC__) && defined(__386__) -#define FAR + #define FAR +#endif +#ifndef __DJGPP__ + static char FAR *scrnPtr; + static char FAR *scrnStealth; + static char FAR *hb_gt_ScreenAddress(void); #endif -static char FAR *scrnPtr; -static char FAR *scrnStealth; -static char FAR *hb_gt_ScreenAddress(void); void hb_gt_Init(void) { +#ifdef __DJGPP__ + gppconio_init(); +#else scrnStealth = (char *)-1; scrnPtr = hb_gt_ScreenAddress(); +#endif } void hb_gt_Done(void) @@ -60,12 +69,12 @@ int hb_gt_IsColor(void) return hb_gt_GetScreenMode() != 7; } +#ifndef __DJGPP__ static char FAR *hb_gt_ScreenAddress() { - char FAR *ptr; -#if defined(__WATCOMC__) && defined(__386__) + #if defined(__WATCOMC__) && defined(__386__) if (hb_gt_IsColor()) { ptr = (char *)(0xB800 << 4); @@ -74,7 +83,7 @@ static char FAR *hb_gt_ScreenAddress() { ptr = (char *)(0xB000 << 4); } -#else + #else if (hb_gt_IsColor()) { ptr = (char FAR *)MK_FP(0xB800, 0x0000); @@ -83,20 +92,25 @@ static char FAR *hb_gt_ScreenAddress() { ptr = (char FAR *)MK_FP(0xB000, 0x0000); } -#endif + #endif return ptr; } +#endif +#ifndef __DJGPP__ char FAR *hb_gt_ScreenPtr(char cRow, char cCol) { return scrnPtr + (cRow * hb_gt_GetScreenWidth() * 2) + (cCol * 2); } +#endif static char hb_gt_GetScreenMode(void) { #if defined(__WATCOMC__) && defined(__386__) return *((char *)0x0449); +#elif defined(__DJGPP__) + return _farpeekb( 0x0040, 0x0049 ); #else return *((char FAR *)MK_FP(0x0040, 0x0049)); #endif @@ -106,6 +120,8 @@ char hb_gt_GetScreenWidth(void) { #if defined(__WATCOMC__) && defined(__386__) return *((char *)0x044a); +#elif defined(__DJGPP__) + return _farpeekb( 0x0040, 0x004a ); #else return *((char FAR *)MK_FP(0x0040, 0x004a)); #endif @@ -115,6 +131,8 @@ char hb_gt_GetScreenHeight(void) { #if defined(__WATCOMC__) && defined(__386__) return (char)(*((char *)0x0484) + 1); +#elif defined(__DJGPP__) + return _farpeekb( 0x0040, 0x0084 ) + 1; #else return (char)(*((char FAR *)MK_FP(0x0040, 0x0084)) + 1); #endif @@ -164,7 +182,6 @@ static void hb_gt_SetCursorSize(char start, char end) static void hb_gt_GetCursorSize(char *start, char *end) { - char _ch,_cl; #if defined(__TURBOC__) _AH = 0x03; _BH = 0; @@ -251,35 +268,86 @@ void hb_gt_SetCursorStyle(int style) static void hb_gt_xGetXY(char cRow, char cCol, char *attr, char *ch) { +#ifdef __DJGPP__ + short ch_attr; + gettext( cCol + 1, cRow + 1, cCol + 1, cRow + 1, &ch_attr ); + *ch = ch_attr >> 8; + *attr = ch_attr & 0xFF; +///printf("\r\nhb_gt_xGetXY(): row == %d, col = %d, char = %d, attr = %d", cRow, cCol, *ch, *attr ); +#else char FAR *p; p = hb_gt_ScreenPtr(cRow, cCol); *ch = *p; *attr = *(p + 1); +#endif } void hb_gt_xPutch(char cRow, char cCol, char attr, char ch) { +#ifdef __DJGPP__ + long ch_attr = ( ch << 8 ) | attr; +///printf("\r\nhb_gt_xPutch(): row == %d, col = %d, char = %d, attr = %d", cRow, cCol, ch, attr ); + puttext( cCol + 1, cRow + 1, cCol + 1, cRow + 1, &ch_attr ); +#else char FAR *p; p = hb_gt_ScreenPtr(cRow, cCol); *p = ch; *(p + 1) = attr; +#endif } void hb_gt_Puts(char cRow, char cCol, char attr, char *str, int len) { +#ifdef __DJGPP__ + int i = len; + int bottom, left = cCol, right, top = cRow; + int width = hb_gt_GetScreenWidth(); + char * ch_attr, * ptr; +///printf("\r\nhb_gt_Puts(): row == %d, col = %d, attr = %d, len = %d", cRow, cCol, attr, len ); + ptr = ch_attr = hb_xgrab( i * 2 ); + while( i-- ) + { +///printf("+"); + *ptr++ = *str++; +///printf("-"); + *ptr++ = attr; + } + i = len - 1; /* We want end position, not next cursor position */ + right = left; + bottom = top; + if (right + i > width - 1) + { + /* Calculate end row position and the remainder size for the end column adjust */ + bottom += (i / width); + i = i % width; + } + right += i; + if (right > width - 1) + { + /* Column movement overflows into next row */ + bottom++; + right -= width; + } +///printf("\r\nhb_gt_Puts(): puttext( %d,%d, %d,%d )", left + 1, top + 1, right + 1, bottom + 1 ); + puttext( left + 1, top + 1, right + 1, bottom + 1, ch_attr ); + hb_xfree( ch_attr ); +#else char FAR *p; int i; - p = hb_gt_ScreenPtr( cRow, cCol ); for(i=0; i 0 - if ( nFound := aScan( aSetKeys, {|x| x[ KEY ] == anKey } ) ) == 0 - if valType( bBlock ) == "B" + elseif valType( anKey ) = "N" .and. anKey <> 0 + if ( nFound := aScan( aSetKeys, {|x| x[ KEY ] = anKey } ) ) = 0 + if valType( bBlock ) = "B" aAdd( aSetKeys, { anKey, bBlock, bCondition } ) endif @@ -103,16 +105,16 @@ Function SetKey( anKey, bBlock, bCondition ) else aKey := aSetKeys[ nFound ] - if aKey[ CONDITION ] == NIL .or. eval( aKey[ CONDITION ], anKey ) + if aKey[ CONDITION ] = NIL .or. eval( aKey[ CONDITION ], anKey ) bReturn := aKey[ BLOCK ] endif - if valType( bBlock ) == "B" + if valType( bBlock ) = "B" aKey[ BLOCK ] := bBlock aKey[ CONDITION ] := bCondition - elseif pcount() > 1 .and. bBlock == NIL + elseif pcount() > 1 .and. bBlock = NIL aSize( aDel( aSetKeys, nFound ), len( aSetKeys ) - 1 ) endif @@ -124,6 +126,56 @@ Function SetKey( anKey, bBlock, bCondition ) return bReturn +/* $DOC$ + * $FUNCNAME$ + * SetKeyGet + * $CATEGORY$ + * ? + * $ONELINER$ + * Determine a set-key code block & condition-block + * $SYNTAX$ + * SETKEYGET( [, ] ) + * $ARGUMENTS$ + * is an numeric key value + * is an optional return-parameter + * $RETURNS$ + * Current assigned action-block + * $DESCRIPTION$ + * The SetKeyGet() function returns the current code-block assigned to a + * key, and optionally assignes the condition-block to the return-parameter + * $EXAMPLES$ + * local bOldF10, bOldF10Cond + * bOldF10 := SetKeyGet( K_F10, @bOldF10Cond ) + * ... // some other processing + * SetKey( K_F10, bOldF10, bOldF10Cond ) + * $TESTS$ + * See test code above + * $STATUS$ + * C + * $COMPLIANCE$ + * SETKEYGET() is a new function and hence not CA-Clipper compliant. + * $SEEALSO$ + * SETKEY(), SETKEYSAVE(), SETKEYCHECK() + * $END$ + */ +Function SetKeyGet( nKey, bCondition ) + local nFound + + if valType( nKey ) = "N" .and. nKey <> 0 + if ( nFound := aScan( aSetKeys, {|x| x[ KEY ] = nKey } ) ) = 0 + bCondition := NIL + + else + bCondition := aSetKeys[ nFound, CONDITION ] + return aSetKeys[ nFound, BLOCK ] + + endif + + endif + +return NIL //bReturn + + /* $DOC$ * $FUNCNAME$ * SetKeySave @@ -162,14 +214,89 @@ return bReturn Function SetKeySave( OldKeys ) local aReturn := aClone( aSetKeys ) - if pcount() != 0 .or. valtype( OldKeys ) == "A" - if OldKeys == NIL + if pcount() != 0 .or. valtype( OldKeys ) = "A" + if OldKeys = NIL aSetKeys := {} else aSetKeys := aClone( OldKeys ) + endif endif return aReturn + + +/* $DOC$ + * $FUNCNAME$ + * SetKeyCheck + * $CATEGORY$ + * ? + * $ONELINER$ + * Impliments common hot-key activation code + * $SYNTAX$ + * SetKeyCheck( [, ][, ][, ] ) + * $ARGUMENTS$ + * is a numeric key value to be tested + * code-block, if executed + * .. are optional parameters that will be passed to the code-block + * $RETURNS$ + * True if there is a hot-key associated with and it was executed; + * otherwise False + * If there is a hot-key association (before checking any condition): + * - if there is a condition-block, it is passed one parameter - + * - when the hot-key code-block is called, it is passed 1 to 4 parameters, + * depending on the parameters passed to SetKeyCheck(). Any parameters + * so passed are directly passed to the code-block, with an additional + * parameter being + * $DESCRIPTION$ + * SetKeyCheck() is intended as a common interface to the SetKey() + * functionality for such functions as ACHOICE(), DBEDIT(), MEMOEDIT(), + * ACCEPT, INPUT, READ, and WAIT + * $EXAMPLES$ + * // within ReadModal() + * if SetKeyCheck( K_ALT_X, GetActive() ) + * ... // some other processing + * endif + * // within TBrowse handler + * case SetKeyCheck( nInkey, oTBrowse ) + * return + * case nInKey == K_ESC + * ... // some other processing + * $TESTS$ + * None definable + * $STATUS$ + * C + * $COMPLIANCE$ + * SetKeyCheck() is new. + * $SEEALSO$ + * SETKEY(), SETKEYSAVE() + * $END$ + */ +Function SetKeyCheck( nKey, p1, p2, p3 ) + local nFound, aKey, bBlock + + if ( nFound := aScan( aSetKeys, {|x| x[ KEY ] = nKey } ) ) > 0 + aKey := aSetKeys[ nFound ] + bBLock := aKey[ BLOCK ] + + if aKey[ CONDITION ] = NIL .or. eval( aKey[ CONDITION ], nKey ) + + // is this overkill? if a code-block checks its own pcount(), + // passing nil parameters would skew the count! + + do case + case pcount() = 1 ; eval( bBlock, nKey ) + case pcount() = 2 ; eval( bBlock, p1, nKey ) + case pcount() = 3 ; eval( bBlock, p1, p2, nKey ) + otherwise ; eval( bBlock, p1, p2, p3, nKey ) + end case + + return .t. + + endif + + endif + +return .f. \ No newline at end of file diff --git a/harbour/tests/working/Makefile b/harbour/tests/working/Makefile index fb7d3a4117..acb27db746 100644 --- a/harbour/tests/working/Makefile +++ b/harbour/tests/working/Makefile @@ -155,6 +155,7 @@ BAD_PRG_SOURCES=\ extend1.prg \ keywords.prg \ linecont.prg \ + setkeys.prg \ spawn.prg \ spawn2.prg \ statics1.prg \ diff --git a/harbour/tests/working/setkeys.prg b/harbour/tests/working/setkeys.prg new file mode 100644 index 0000000000..979fc19d7e --- /dev/null +++ b/harbour/tests/working/setkeys.prg @@ -0,0 +1,84 @@ +/* + * $Id$ + + Harbour Project source code - http://www.Harbour-Project.org + + By: A White - awhite@user.rose.com + + This file contains the Harbour function(s) that maintain the list + of set-keys (hot-keys). + + 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 of the License, or + (at your option) any later version, with one exception: + + The exception is that if you link the Harbour Runtime Library (HRL) + and/or the Harbour Virtual Machine (HVM) 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 HRL + and/or HVM code into it. + + 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 program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + their web site at http://www.gnu.org/). + + V 1.0 A White Initial version, submitted to Harbour Project +*/ + + #include "inkey.ch" + Procedure Main() + local GetList := {} + local alpha, bravo, charlie, k + + cls + + @ 2, 2 say "Press F10 to popup alert box of current get, not active if empty" + @ 3, 2 say "Press F9 to disable all setkeys, except F9 to restore (uses SetKeySave())" + @ 4, 2 say "Press F8 to test setkey w/ array, and SetKeyCheck()" + + alpha := "alpha " + bravo := 123 + charlie := date() + + @ 10, 10 get alpha + @ 11, 10 get bravo + @ 12, 10 get charlie + + #ifndef K_F10 + + #define K_F10 -9 + #define K_F9 -8 + #define K_F8 -7 + #define K_ESC 27 + + #endif + + setKey( K_F10, {|| Alert( transform( getactive():varGet(), NIL ) ) }, {|| !empty( getactive():buffer ) } ) + setKey( K_F9 , {|| k := SetKeySave( NIL ), ; + SetKey( K_F9, {|| SetKeySave( k ) } ) } ) + SetKey( K_F8 , {|| SubMain() } ) + + read + ? alpha, bravo, charlie + + + static Procedure SubMain() + local n + SetKey( { 49, 50, 52, 53 }, {|x| qout( chr( x ) ) } ) + do while ( n := inkey( 0 ) ) != K_ESC + if SetKeyCheck( n ) + qqout( " hit hot" ) + else + qout( chr( n ) ) + qqout( " hit cold" ) + endif + end + SetKey( { 49, 50, 52, 53 }, NIL )