tab_hell.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 617 行

C
617
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "vi.h"

long TabCnt;

/*
 * getNextPos - get next cursor position, given current
 */
static bool getNextPos( int ch, int *opos )
{
    int pos;

    pos = *opos;

    if( ch < ' ' || ch > 127 ) {
        if( ch == '\t' ) {
            #ifndef __WIN__
                if( EditFlags.RealTabs ) {
                    pos += Tab( pos+1, HardTab );
                } else {
                    pos ++;
                }
            #else
                pos += Tab( pos+1, HardTab );
            #endif
        } else if ( ch == 0 ) {
            return( FALSE );
        } else if( EditFlags.EightBits ) {
            pos ++;
        } else {
            pos +=2;
        }
    } else {
        pos ++;
    }
    *opos = pos;
    return( TRUE );

} /* getNextPos */

/*
 * InsertTabSpace - insert tabs and white space
 */
int InsertTabSpace( int j, char *buff, bool *tabme )
{
    int n,extra,m,i;
    int k=0;

    if( *tabme ) {
        *tabme = FALSE;
        n = HardTab - Tab(j+1, HardTab);
        extra = j-n;
        if( extra > 0 ) {
            m = extra/HardTab;
            if( extra % HardTab > 0 ) {
                m++;
            }
            TabCnt += m;
            *tabme = TRUE;
            for( i=0;i<m;i++ ) {
                buff[k++] = '\t';
            }
        } else {
            n = j;
        }
    } else {
        n = j;
    }

    /*
     * put in extra spaces
     */
    for( i=0;i<n;i++ ) {
        buff[k++] = ' ';
    }
    return( k );

} /* InsertTabSpace */


/*
 * ExpandTabsInABufferUpToColumn - remove tabs only up to specified column
 */
bool ExpandTabsInABufferUpToColumn( int endcol, char *in, int inlen, char *out, int outlen  )
{
    int         i,j;
    bool        res;

    res = ExpandTabsInABuffer( in, endcol, out, outlen );
    j = inlen - endcol;
    i = strlen( out );
    if( i+j >= outlen ) {
        inlen = outlen - i + endcol;
    }
    for( j=endcol;j<inlen;j++) {
        out[i++] = in[j];
    }
    out[i] = 0;
    return( res );

} /* ExpandTabsInABufferUpToColumn */

/*
 * ExpandTabsInABuffer - do all tabs in a buffer
 */
bool ExpandTabsInABuffer( char *in, int inlen, char *out, int outlen  )
{
    int         j,k,tb,l;
    bool        tabme = FALSE;
    char        ch;

    /*
     * run through each character
     */
    k = 0;
    outlen--;
    for(j=0;j<inlen;j++) {
        /*
         * if we have a tab, insert some spaces
         */
        if( in[j] < ' ' || in[j] > 127 ) {
            if( in[j] == '\t' ) {
                TabCnt++;
                tb = Tab( k+1, HardTab );
                for(l=k;l<k+tb;l++) {
                    if( l < outlen ) {
                        out[l] = ' ';
                    } else {
                        out[outlen]=0;
                        return( TRUE );
                    }
                }
                k = l;
                tabme = TRUE;
            } else if( !EditFlags.EightBits ) {
                if( in[j] > 127 ) {
                    ch = '?';
                } else {
                    ch = in[j]+'A'-1;
                }
                if( k+1 < outlen ) {
                    out[k++] = '^';
                    out[k++] = ch;
                } else {
                    out[outlen]=0;
                    return( TRUE );
                }
                tabme = TRUE;
            } else {
                out[k++] = in[j];
            }
        } else {
            if( k+1 >= outlen ) {
                break;
            } else {
                out[k++] = in[j];
            }
        }

    }
    out[k] = 0;
    return( tabme );

} /* ExpandTabsInABuffer */


// These 2 routines are prefered if you want a position on
// the screen (not a "cursor" position)

/*
 * WinVirtualCursorPosition - same as below but ignores goofy
 *                            insert mode considerations.
 *                            curs is base 1
 *                            returned coordinates are base 1
 */
int WinVirtualCursorPosition( char *buff, int curs )
{
    int j;
    int pos=0;

    for(j=0;j<curs;j++) {
        if( !getNextPos( buff[j], &pos ) ) {
            break;
        }
    }
    if( pos == 0 ) {
        pos = 1;
    }
    return( pos );
}
/*
 * WinRealCursorPosition - compute the real cursor position in the given
 *                      line, given the virtual position
 *                      vc is base 1
 *                      returned coordinates are base 1
 */
int WinRealCursorPosition( char *buff, int vc )
{
    int         pos, i, len;

    len = strlen( buff );
    pos = 0;
    for( i = 0; i < len; i++ ) {
        if( !getNextPos( buff[ i ], &pos ) ) {
            break;
        }
        if( pos >= vc ) {
            return( i + 1 );
        }
    }
    return( len );
} /* WinRealCursorPosition */



/*
 * GetVirtualCursorPosition - get the virtual position of the cursor, given
 *                            the real position on the current line
 */
int GetVirtualCursorPosition( char *buff, int curs )
{
    int j;
    int pos=0;

    /*
     * run through each character
     */
    if( EditFlags.InsertModeActive || EditFlags.Modeless ) {
        curs--;
    }
    for(j=0;j<curs;j++) {
        if( !getNextPos( buff[j], &pos ) ) {
            break;
        }
    }
    if( EditFlags.InsertModeActive || EditFlags.Modeless ) {
        return( pos + 1 );
    }
    if( pos == 0 ) {
        pos = 1;
    }
    return( pos );

} /* GetVirtualCursorPosition */

int VirtualCursorPosition( void )
{
    return( VirtualCursorPosition2( CurrentColumn ) );
} /* VirtualCursorPosition */

/*
 * VirtualCursorPosition2 - compute the screen position of a specified
 *                          column in the current line
 */
int VirtualCursorPosition2( int ccol )
{
    int col;

    if( CurrentLine == NULL ) {
        return( 1 );
    }

    if( ccol == 0 ) {
        col = 1;
    } else {
        col = ccol;
    }
    if( CurrentLine->inf.ld.nolinedata ) {
        return( GetVirtualCursorPosition( WorkLine->data, col ) );
    } else {
        return( GetVirtualCursorPosition( CurrentLine->data, col ) );
    }

} /* VirtualCursorPosition2 */




/*
 * realPosition
 */
int realPosition( int virt_pos, char *buff, int len )
{
    int         j;
    int         pos=0;

    if( EditFlags.Modeless ) {
        len++;
    }

    for(j=0; j < len; j++ ) {
        if( !getNextPos( buff[ j ], &pos ) ) {
            break;
        }
        if( pos >= virt_pos ) {
            return( j + 1 );
        }

    }
    return( len );
} /* realPosition */

/*
 * RealCursorPosition - compute the real cursor position on the current
 *                      line, given the virtual position
 */
int RealCursorPosition( int vc )
{
    int         cl;
    char        *buff;

    if( CurrentLine->inf.ld.nolinedata ) {
        cl = WorkLine->len;
        buff = WorkLine->data;
    } else {
        cl = CurrentLine->len;
        buff = CurrentLine->data;
    }
    return( realPosition( vc, buff, cl ) );
} /* RealCursorPosition */

/*
 * CursorPositionOffRight - determine if cursor is beyond the end of text
 */
int CursorPositionOffRight( int vc )
{
    int         cl,j, pos=0;
    char        *buff;


    if( CurrentLine->inf.ld.nolinedata ) {
        cl = WorkLine->len;
        buff = WorkLine->data;
    } else {
        cl = CurrentLine->len;
        buff = CurrentLine->data;
    }
    if( cl == 0 ) return( FALSE );

    if( EditFlags.Modeless ) {
        cl++;
    }

    for(j=0; j < cl; j++ ) {
        if( !getNextPos( buff[ j ], &pos ) ) {
            break;
        }
        if( pos >= vc ) {
            return( FALSE );
        }

    }
    return( TRUE );
} /* CursorPositionOffRight */

int RealCursorPositionInString( char *buff, int virt_pos )
{
    int real_pos = realPosition( virt_pos, buff, strlen(buff) );
    return( real_pos );
}

int RealCursorPositionOnLine( linenum line_num, int virt_pos )
{
    line        *line;
    fcb         *fcb;
    int         i, real_pos;

    real_pos = -1;
    i = CGimmeLinePtr( line_num, &fcb, &line );
    if( i == ERR_NO_ERR ) {
        real_pos = realPosition( virt_pos, line->data, line->len );
    }
    return( real_pos );
} /* RealCursorPositionOnLine */

/*
 * RealLineLen - compute the real length of a specified line
 */
int RealLineLen( char *buff )
{
    int j,cl;
    int pos=0;

    cl = strlen( buff );
    for(j=0;j<cl;j++) {
        if( !getNextPos( buff[j], &pos ) ) {
            break;
        }
    }
    return( pos );

} /* RealLineLen */

/*
 * AddLeadingTabSpace - make leading spaces tabs (if possible)
 */
int AddLeadingTabSpace( short *len, char *buff, int amount )
{
    char        *tmp;
    int         start=0,i=0;
    int         j,k,l;
    bool        tabme;
    bool        full = FALSE;

    /*
     * expand leading stuff into spaces
     */
    j = *len;
    while( isspace( buff[start] ) ) {
        start++;
    }
    tmp = StaticAlloc();
    ExpandTabsInABuffer( buff, j,  tmp, MaxLine );
    while( tmp[i] == ' ' ) {
        i++;
    }

    /*
     * subtract/add extra spaces
     */
    if( amount <= 0 ) {
        k = i + amount;
        if( k < 0 ) {
            k = 0;
        }
    } else {
        if( i+amount >= MaxLine ) {
            full = TRUE;
            k = i;
        } else {
            for( k=i;k<i+amount;k++ ) {
                tmp[k] = ' ';
            }
        }
    }
    tmp[k] = 0;

    /*
     * change spaces to tabs, and add the rest of the line back
     */
    tabme = EditFlags.RealTabs;
    if( k > 0 ) {
        k = InsertTabSpace( k, tmp, &tabme );
    }
    for( l=start;l<=j;l++ ) {
        tmp[k++] = buff[l];
    }
    memcpy( buff, tmp, k );
    StaticFree( tmp );
    *len = (k-1);
    return( (int) full );

} /* AddLeadingTabSpace */


/*
 * ConvertSpacesToTabsUpToColumn - add tabs only up to specified column
 */
bool ConvertSpacesToTabsUpToColumn( int endcol, char *in, int inlen, char *out, int outlen  )
{
    int         first_blank,j,extra,l,n,k,m,i;
    bool        blanks_inprog,tabme;
    char        c,oc;
    bool        in_quotes;
    bool        in_single_quotes;
    bool        esc;

    /*
     * init for this line
     */
    k = 0;
    first_blank = 0;
    blanks_inprog = FALSE;
    tabme = FALSE;
    in_quotes = FALSE;
    in_single_quotes = FALSE;
    esc = FALSE;

    /*
     * run through each character
     */
    oc = in[endcol];
    in[endcol] = 0;
    for(j=0;j<=endcol;j++) {

        c = in[j];
        if( c != ' ' || in_quotes || in_single_quotes ) {

            /*
             * if last char was blank, special processing
             */
            if( blanks_inprog ) {
                /*
                 * work out number of tabs and spaces
                 * that need to be added
                 */
                blanks_inprog = FALSE;
                l = j - first_blank;
                if( l > 1 ) {
                    n = HardTab - Tab(j+1, HardTab);
                    extra = l-n;

                    /*
                     * add tabs, then spaces
                     */
                    if( extra > 0 ) {
                        m = extra/HardTab;
                        if( extra % HardTab > 0 ) {
                            m++;
                        }
                        TabCnt += m;
                        tabme = TRUE;
                        if( k+m >= outlen ) {
                            m = outlen-k;
                        }
                        for( i=0;i<m;i++ ) {
                            out[k++] = '\t';
                        }
                    } else {
                        n = l;
                    }
                    if( k+n >= outlen ) {
                        n = outlen-k;
                    }
                    for( i=0;i<n;i++ ) {
                        out[k++] = ' ';
                    }
                } else {
                    if( k+1 < outlen ) {
                        out[k++] = ' ';
                    }
                }
            }
            if( k+1 >= outlen ) {
                break;
            }
            if( !esc ) {
                if( c == '\'' ) {
                    if( !in_quotes ) {
                        in_single_quotes = !in_single_quotes;
                    }
                } else if( c == '"' ) {
                    in_quotes = !in_quotes;
                } else if( c == '\\' ) {
                    esc = TRUE;
                }
            } else {
                esc = FALSE;
            }
            out[k++] = c;
            if( c == 0 ) {
                break;
            }

        } else {
            /*
             * mark start of blanks
             */
            if( !blanks_inprog ) {
                first_blank = j;
                blanks_inprog = TRUE;
            }

        }

    }

    /*
     * copy the rest
     */
    k--;
    in[endcol] = oc;
    if( k+inlen >= outlen ) {
        inlen = outlen-k;
    }
    for( j=endcol;j<inlen;j++ ) {
        out[k++] = in[j];
    }
    out[k++] = 0;
    return( tabme );

} /* ConvertSpacesToTabsUpToColumn */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?