Function MlCtoPos() Foundation

Determines the position of a character in a formatted character string.

Syntax
MlCtoPos( <cString>  , ;
          <nLineLen> , ;
          <nRow>     , ;
          <nCol>     , ;
         [<nTabSize>], ;
         [<lWrap>]     ) --> nPosition
Parameters
<cString>
<cString> is a character string which may contain formatting characters like tab (Chr(9)) or return (Chr(13)+Chr(10)).
<nLineLen>
<nLineLen> is an integer numeric value specifying the maximum length of a line in <cString>.
<nRow>
<nRow> specifies the row in which the character is found. The row counter begins with one.
<nCol>
<nCol> specifies the column within the row in which the character is found. The column counter begins with zero.
<nTabSize>
The tab size is indicated by <nTabSize>. The default value is four characters per tab. The tab size must be smaller than <nLineLen> - 1.
<lWrap>
The logical value for <lWrap> indicates whether automatic word wrap is taken into consideration. The default value is .T. (true) which indicates that automatic word wrapping is taken into consideration. When the value .F. (false) is specified, word wrap is not taken into consideration.
Return

The function MlCtoPos() calculates the position of a character in the formatted character string <cString> based on the specified row and column. The character position counter begins with the value one.

Description

The memo function MlCtoPos() determines the exact position of a character in a formatted character string based on row and column position within the text. Formatting characters like tab (Chr(9)) and return are considered in determining the return value. The row position begins with the value one and the column position begins with zero. The counter for the return value (position of the character in <cString>) begins with one. Further processing can be performed using SubStr() based on this position.

The function MlCtoPos() is often used with MPostoLc(). For example, these functions might be used to program text search routines for MemoEdit().

Examples
Search routine for MemoEdit()

// The example shows an extensive MemoEdit() routine using a 
// user function. From the user function a search routine 
// can be started with Alt+S. In the UDF MemoSeek(), a search 
// expression is input by the user. When the expression 
// is found, the cursor is positioned in the MemoEdit() text buffer 
// on the first character in the search expression. Note the 
// STATIC file-wide variables. 

#include "Inkey.ch" 
#include "Setcurs.ch" 
#include "Memoedit.ch" 

STATIC snWinRow , snWinCol, snBuffRow, snBuffCol 
STATIC snTop    , snLeft  , snBottom , snRight 

STATIC slExit    := .F. 
STATIC snTabsize := 3 
STATIC snLineLen := 128 

************** 
PROCEDURE Main 

   ? FileEdit( "TEST.PRG", 2, 2, 22, 76 ) 
   Inkey(0) 

RETURN 

***************** 
FUNCTION FileEdit( cFilename, nTop, nLeft, nBottom, nRight ) 
   LOCAL lUpdated := .F. 
   LOCAL cString  := MemoRead( cFilename ) 
   LOCAL cScreen  := SaveScreen( nTop, nLeft, nBottom, nRight ) 

   snTop     :=  nTop    + 1    // initialize 
   snLeft    :=  nLeft   + 1    // static variables 
   snBottom  :=  nBottom - 1 
   snRight   :=  nRight  - 1 
   snWinRow  :=  0 
   snWinCol  :=  0 
   snBuffRow :=  1 
   snBuffCol :=  0 
   slExit    := .F. 

   SET SCOREBOARD OFF 

   DO WHILE .NOT. slExit 
                                // display box with title 
      DispBox( nTop, nLeft, nBottom, nRight, 2 ) 
      @ nTop, nLeft+1 SAY ; 
              PadC(cFileName, nRight-nLeft-1, Chr(205) ) 

                                // edit text 
      cString := MemoEdit( cString    , ; 
                           snTop      , ; 
                           snLeft     , ; 
                           snBottom   , ; 
                           snRight    , ; 
                           .T.        , ; 
                           "UserFunc" , ; 
                           snLineLen  , ; 
                           snTabSize  , ; 
                           snBuffRow  , ; 
                           snBuffCol  , ; 
                           snWinRow   , ; 
                           snWinCol     ) 
      IF ! slExit 
         MemoSeek( cString )    // call search function 
      ENDIF 
   ENDDO 

   SET SCOREBOARD ON 
   RestScreen( nTop, nLeft, nBottom, nRight, cScreen ) 

RETURN MemoWrit( cFilename, cString ) 

****************** 
PROCEDURE MemoSeek( cString ) 
   LOCAL cSeek := Space( 40 ), nPos, aPos, nFound 

   // Get search expression 
   @ snBottom+1, snLeft SAY "Search:" GET cSeek 
   READ 
   cSeek := Upper( Trim( cSeek ) ) 

   IF ! Empty( cSeek ) 
      // find current position in the text buffer 
      nPos := MlCtoPos( cString  , ; 
                        snLineLen, ; 
                        snBuffRow, ; 
                        snBuffCol, ; 
                        snTabSize  ) 

      // search forward only for expression 
      nFound := At( cSeek, SubStr( Upper( cString ), nPos+1 ) ) 

      IF nFound > 0 
         nPos += nFound 

         // find corresponding row and column 
         // in the text buffer 
         aPos := MPostoLc( cString  , ; 
                           snLineLen, ; 
                           nPos     , ; 
                           snTabSize  ) 

         // new position in the window of MemoEdit() 
         snWinRow  += ( aPos[1] - snBuffRow ) 
         snWinCol  += ( aPos[2] - snBuffCol ) 

         // new position in the text buffer for MemoEdit() 
         snBuffRow := aPos[1] 
         snBuffCol := aPos[2] 

      ELSE 
         @ snBottom+1, snLeft SAY ; 
           PadR("Not found!",snRight-snLeft-1, Chr(205) ) 
         Inkey(0) 
      ENDIF 
   ENDIF 

RETURN 

****************** 
FUNCTION UserFunc( nMode, nRow, nCol ) 
   LOCAL nKey    := LastKey() 
   LOCAL nReturn := ME_DEFAULT         // default return value 

   snBuffRow := nRow 
   snBuffCol := nCol 
   snWinRow  := Row() - snTop 
   snWinCol  := Col() - snTop 

   DO CASE 
   CASE nMode == ME_IDLE               // display position in 
      nRow := Row()                    // the text buffer 
      nCol := Col() 
      SetPos( snBottom+1, snLeft ) 
      ??  "Row:" , Str(snBuffRow,4) 
      ?? " Column:", Str(snBuffCol,2) 
      SetPos( nRow, nCol ) 

   CASE nMode == ME_UNKEY .OR. nMode == ME_UNKEYX 

      DO CASE 
      CASE nKey == K_F7                // next word with F7 
         nReturn:= ME_WORDRIGHT 

      CASE nKey == K_F8                // last character in the 
         nReturn:= ME_BOTTOMRIGHT      // window with F8 

      CASE nKey == K_F9                // switch word wrap 
         nReturn:= ME_TOGGLEWRAP       // with F9 

      CASE nKey == K_F10               // switch scroll 
         nReturn:= ME_TOGGLESCROLL     // with F10 

      CASE nKey == K_CTRL_RET .OR. ;   // save on Ctrl-Return 
           nKey == K_CTRL_W 
         slExit := .T. 
         nReturn:= K_CTRL_W 

      CASE nKey == K_ESC 
         slExit := .T. 

      CASE nKey == K_ALT_S             // terminate and search 
         nReturn:= K_CTRL_W 

      CASE nKey == K_INS               // set cursor based on 
         IF SetCursor() == SC_SPECIAL1 // insertion mode 
            SetCursor( SC_NORMAL ) 
         ELSE 
            SetCursor( SC_SPECIAL1 ) 
         ENDIF 
      ENDCASE 

   OTHERWISE                           // on initialization 
      nReturn := IIf( ReadInsert(), 0, K_INS ) 
                                       // switch to insertion 
      SetCursor( SC_SPECIAL1 )         // mode by default 

   ENDCASE 

RETURN nReturn 

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.