/* * File......: DISPMSG.PRG * Author....: Paul Ferrara, ColumbuSoft * CIS ID....: 76702,556 * * This function is an original work by Paul Ferrara and is placed in the * public domain. * * Modification history: * --------------------- * * Rev 2.0 12 Aug 1994 23:05:14 PAUL * Added ablilty to highlight individual characters and cleaned up code * * Rev 1.2 15 Aug 1991 23:05:14 GLENN * Forest Belt proofread/edited/cleaned up doc * * Rev 1.1 14 Jun 1991 19:51:36 GLENN * Minor edit to file header * * Rev 1.0 01 Apr 1991 01:01:12 GLENN * Nanforum Toolkit * */ /* $DOC$ * $FUNCNAME$ * FT_DISPMSG() * $CATEGORY$ * Menus/Prompts * $ONELINER$ * Display a message and optionally waits for a keypress * $SYNTAX$ * FT_DISPMSG( , [ ], * [ ], [ ], * [ ], [ ] ) -> lKeyMatch * $ARGUMENTS$ * is a multidimensional array of messages to be * displayed and the color attributes for each message. * * The first dimension of the array contains one or more elements, * each representing one line in the message box, up to the maximum * number of rows on the screen. * * Within each line of the message individual characters or groups * of characters may be delimited with braces ([]). The braces will * be stripped out and the character(s) inside those braces will be * highlighted. * * The second dimension of the array contains a color attribute for * the corresponding element in dimension one, plus one additional * element for the color of the box border. Dimension two will * always contain one more element than dimension one. If an * attribute is omitted, the last color selected will be used. * * is a character string of one or more keys to check * for. If omitted, the message is displayed and control is returned * to the calling procedure. If one character is specified, * FT_DISPMSG() waits for one keypress, restores the screen and * returns. If multiple characters are specified, FT_DISPMSG() * remains in a loop until one of the specified keys has been * pressed, then restores the screen and returns. * * is the upper row for the message box. If omitted, the * box is centered vertically. * * is the leftmost column for the box. If omitted, the * box is centered horizontally. * * is a string of characters or a variable for the box * border. See the DISPBOX() function. If omitted, a double box is * drawn. * * is a logical variable. If true (.T.) or omitted, it * uses FT_SHADOW() to add a transparent shadow to the box. If * false (.F.), the box is drawn without the shadow. * $RETURNS$ * If is not specified, FT_DISPMSG() will return false * (.F.). * * If is a one-character string, FT_DISPMSG() will return * true (.T.) if the user presses that key, or false (.F.) if any * other key is pressed. * * If consists of multiple characters, it will lock the * user in a loop until one of those keys are pressed and return the * INKEY() value of the keypress. * $DESCRIPTION$ * FT_DISPMSG() is a multi-purpose pop-up for user messages. * Multiple lines may be displayed, each with a different attribute. * The box will be automatically centered on the screen, or the row * and/or column can be specified by the programmer. It also centers * each line of the message within the box. * $EXAMPLES$ * The following example displays a simple two-line message * and returns immediately to the calling routine. * * FT_DISPMSG( { { "Printing Report" , ; * "Press [ESC] To Interrupt" } , ; * { "W+/B*", "W/B", "GR+/B" } } ) * * The next example displays a message and waits for a key press. * * FT_DISPMSG( { { "Press [D] To Confirm Deletion" , ; * "Or Any Other Key To Abort" } , ; * { "W+/B", "W+/B", "GR+/B" } } , ; * "D" ) * * The next example displays a one-line message centered on row 5 * and returns to the calling procedure. * * FT_DISPMSG( { { "Please Do Not Interrupt" } , ; * { "W+/B", "GR+/B" } } , ; * , 5, ) * $END$ */ #include "inkey.ch" // beginning of demo program #ifdef FT_TEST // color variables STATIC cNormH, cNormN, cNormE, ; cWindH, cWindN, cWindE, ; cErrH, cErrN, cErrE PROCEDURE Main( cCmdLine ) LOCAL cDosScrn, ; nDosRow, ; nDosCol, ; lColor, ; nMaxRow, ; nType // main routine starts here SET SCOREBOARD OFF lColor := .T. cNormH := IIF( lColor, "W+/BG","W+/N" ) cNormN := IIF( lColor, "N/BG" ,"W/N" ) cNormE := IIF( lColor, "N/W" , "N/W" ) cWindH := IIF( lColor, "W+/B", "W+/N" ) cWindN := IIF( lColor, "W/B" , "W/N" ) cWindE := IIF( lColor, "N/W" , "N/W" ) cErrH := IIF( lColor, "W+/R", "W+/N" ) cErrN := IIF( lColor, "W/R" , "W/N" ) cErrE := IIF( lColor, "N/W" , "N/W" ) cDosScrn := SAVESCREEN() nDosRow=ROW() nDosCol=COL() SETCOLOR( "W/N" ) CLS nMaxRow := MAXROW() SETBLINK(.F.) SETCOLOR( cWindN + "*" ) CLS SETCOLOR( cNormN ) FT_DispMsg( { { "[Esc] To Abort Changes [PgDn] To Continue" }, { cNormN, , cNormH } }, , nMaxRow - 5 ) FT_DispMsg( { { "[E]dit [P]rint [D]elete", ; "[Esc]ape [Alt-Q]" }, ; { cErrN, cErrN, cErrH } },, 2 ) nType := FT_DispMsg( { { "Create Or Edit [I]nvoice", ; "Create Or Edit [O]rder", ; "Create Or Edit [B]ack Order", ; "Create Or Edit [Q]uote", ; "[Esc] To Exit" }, ; { cWindN,,,,, cWindH } }, "BIOQ" + CHR(27) ) SETCOLOR( "W/N" ) SETCURSOR( 1 ) SETBLINK( .T.) RESTSCREEN(,,,, cDosScrn ) SETPOS(nDosRow, nDosCol) QUIT #endif // end of demo program FUNCTION FT_DispMsg( aInfo, cKey, nBoxTop, nBoxLeft, cnBoxString, lShadow ) LOCAL xRtnVal := .F., ; nWidest := 0, ; nBoxRight, ; nBoxBottom, ; cOldScreen, ; cOldCursor, ; cOldColor, ; i, ; j, ; nOption, ; x, ; y, ; aPos := {}, ; nLeft, ; nTop, ; aLeft, ; cLeftMarker, ; cRightMarker FOR i := 1 TO LEN( aInfo[1] ) AADD( aPos, {} ) NEXT FOR i := 1 TO LEN( aInfo[1] ) DO WHILE AT( "[", aInfo[1,i] ) > 0 x := AT( "[", aInfo[1,i] ) y := AT( "]", aInfo[1,i] ) - 2 AADD( aPos[i], { x, y } ) aInfo[1,i] := STRTRAN( aInfo[1,i], "[", "", 1, 1 ) aInfo[1,i] := STRTRAN( aInfo[1,i], "]", "", 1, 1 ) ENDDO NEXT AEVAL( aInfo[1], {|x| nWidest := MAX( nWidest, LEN( x ) ) } ) /* calculate location of data */ IF nBoxLeft == NIL nLeft := ROUND( ( MAXCOL() - nWidest ) / 2, 0 ) ELSE nLeft := nBoxLeft + 2 ENDIF IF nBoxTop == NIL nTop := ( MAXROW() - LEN( aInfo[1] ) - 2 ) / 2 + 2 ENDIF /* calculate location of box */ IF nBoxLeft == NIL nBoxLeft := nLeft - 2 ENDIF nBoxRight := nBoxLeft + nWidest + 3 IF nBoxTop == NIL nBoxTop := (MAXROW() - LEN( aInfo[1] ) - 2) / 2 + 1 ENDIF nBoxBottom := nBoxTop + LEN( aInfo[1] ) + 1 // following is to keep from breaking old code and to be // consistent with DISPBOX() IF cnBoxString == NIL .OR. cnBoxString == 2 cnBoxString := "ÉÍ»º¼ÍȺ " ELSEIF cnBoxString == 1 cnBoxString := "ÚÄ¿³ÙÄÀ³ " ENDIF lShadow := IIF( lShadow == NIL, .T., lShadow ) cOldScreen := SAVESCREEN( nBoxTop, nBoxLeft, nBoxBottom+1, nBoxRight+2 ) cOldCursor := SETCURSOR( 0 ) // draw box cOldColor := SETCOLOR( aInfo[ 2, LEN( aInfo[2] ) ] ) DISPBOX( nBoxTop, nBoxLeft, nBoxBottom, nBoxRight, cnBoxString, ; aInfo[ 2, LEN( aInfo[2] ) ] ) IF lShadow FT_Shadow( nBoxTop, nBoxLeft, nBoxBottom, nBoxRight ) ENDIF /* fill array with left positions for each row */ aLeft := ARRAY( LEN( aInfo[1] ) ) FOR i := 1 TO LEN( aInfo[1] ) IF LEN( aInfo[1,i] ) = nWidest aLeft[i] := nLeft ELSE aLeft[i] := nLeft + ROUND( ( nWidest - LEN( aInfo[1,i] ) ) / 2, 0 ) ENDIF NEXT /* fill array of colors */ FOR i := 2 TO LEN( aInfo[2] ) IF aInfo[2,i] == NIL aInfo[2,i] := aInfo[2,i-1] ENDIF NEXT /* display messages */ FOR i := 1 TO LEN( aInfo[1] ) @ nBoxTop+i, aLeft[i] SAY aInfo[1,i] COLOR aInfo[2,i] NEXT /* highlight characters */ FOR i := 1 TO LEN( aPos ) FOR j := 1 TO LEN( aPos[i] ) FT_SetAttr( nBoxTop + i, ; aPos[i,j,1] + aLeft[i] - 1, ; nBoxTop + i, ; aPos[i,j,2] + aLeft[i] - 1, ; FT_Color2N( aInfo[ 2, LEN( aInfo[2] ) ] ) ) NEXT NEXT IF cKey != NIL IF LEN( cKey ) == 1 nOption := FT_SInkey(0) IF UPPER( CHR( nOption) ) == cKey xRtnVal := .t. ENDIF ELSE nOption := 0 DO WHILE AT( UPPER( CHR( nOption ) ), UPPER( cKey ) ) == 0 nOption := FT_SInkey(0) ENDDO xRtnVal := nOption ENDIF RESTSCREEN( nBoxTop, nBoxLeft, nBoxBottom+1, nBoxRight+2, cOldScreen ) ENDIF SETCOLOR( cOldColor ) SETCURSOR( cOldCursor ) RETURN xRtnVal