home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Best Objectech Shareware Selections
/
UNTITLED.iso
/
boss
/
word
/
text
/
019
/
cmds.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
23KB
|
1,154 lines
/*
* Copyright (c) 1992 John E. Davis (davis@amy.tch.harvard.edu)
* All Rights Reserved.
*/
#include <stdio.h>
#include <string.h>
#include "slang.h"
#include "buffer.h"
#include "screen.h"
#include "window.h"
#include "ins.h"
#include "ledit.h"
#include "cmds.h"
#include "line.h"
#include "paste.h"
#include "display.h"
#include "vterm.h"
#include "sysdep.h"
#include "text.h"
#include "file.h"
#include "misc.h"
#include "search.h"
int Last_Command_Char;
int Blink_Flag = 1;
static char *Top_Of_Buffer_Error = "Top Of Buffer.";
static char *End_Of_Buffer_Error = "End Of Buffer.";
/* return 1 if line extends beyond the screen */
int long_line(void)
{
int p, col;
col = Screen_Col;
p = Point;
Point = CLine->len - 1;
if (*(CLine->data + Point) != '\n') Point++;
if (calculate_column() >= Window->width - 1)
{
Point = p;
Screen_Col = col;
return(1);
}
Screen_Col = col;
Point = p;
return(0);
}
#define FAST_NOT_OK ((Repeat_Factor != NULL) || Window->trashed\
|| (ch < ' ') || (ch > 126)\
|| (Screen_Col >= Window->width - 2) || (Window->column > 1)\
|| input_pending(2, 0) || long_line() || tabs_present())
/* This routine moves CLine and point to the matching '{' or whatever. It
returns 1 if it lies outside the screen, 0 if inside and -1 if not found
and -2 if it looked back for more than 100 lines and not found. It
can get messed up if there are delimeters in comments unless they are
properly enclosed like the above */
/* count is the number of lines to go back and shift is distance back to
start searching from. (usually 0, 1, or 2) */
int find_matching(char ch, int count, int shift)
{
int n = 1, slash, ret = 0, lang = ! (CBuf->modes == WRAP_MODE);
unsigned char *p, *prev, *p1;
char ch1, in, save;
char quote = '\\';
char cb1 = '/', cb2 = '*', ce1 = '*', ce2 = '/';
int inc = 0;
ch1 = '(';
if (ch == '}') ch1 = '{'; else if (ch == ']') ch1 = '[';
p = CLine->data + Point - shift;
if (p < CLine->data)
{
if (CLine->prev == NULL) return(-1);
if (CLine == Window->beg.line) ret = 1;
CLine = CLine->prev;
p = CLine->data + (CLine->len - 1);
}
in = 0;
if (Point > 1) prev = p - 1; else prev = p;
while(count)
{
p1 = p - 1;
if (lang && !inc && ((*p == '\'') || (*p == '"')))
{
slash = 0;
save = *p;
while((p > CLine->data) && (*(p - 1) == quote))
{
p--;
slash = !slash;
}
if (!slash)
{
if (in == 0) in = save; else if (in == save) in = 0;
}
}
if (!in)
{
/* This is specific to C. I need to generalize to other languages. */
if (lang && (ce2 == *p) && (p > CLine->data)
&& (*p1 == ce1))
{
p = p1;
inc = 1;
}
else if (lang && (cb2 == *p) && (p > CLine->data)
&& (*p1 == cb1))
{
if (inc == 0) return (-2);
p = p1;
inc = 0;
}
if (!inc && ((*p == '[') || (*p == '{') || (*p == '('))) n--;
else if (!inc && ((*p == '}') || (*p == ']') || (*p == ')'))) n++;
}
if (!n) break;
if ((p == CLine->data) && (CLine == Window->beg.line)) ret = 1;
if (p == CLine->data)
{
if (CLine->prev == NULL) break;
CLine = CLine->prev;
count--;
p = CLine->data + (CLine->len - 1);
}
else p--;
}
Point = (int) (p - CLine->data);
if ((n == 0) && (*p == ch1)) return(ret);
if (lang) if ((*prev == '\'') || (*prev == '"')) return(-2);
return(-1);
}
/* blink the matching fence. This assumes that the window is ok */
void blink_match(char ch)
{
Line *save;
int pnt, code, matchp;
char buf[600];
if (!Blink_Flag || (Repeat_Factor != NULL) || Window->trashed) return;
pnt = Point;
save = CLine;
code = find_matching(ch, 100, 2);
if (code == -1)
{
if ((! (CBuf->modes == WRAP_MODE)) && (!IS_MINIBUFFER)) message("Mismatch??");
}
else if (code == 0)
{
point_cursor();
fflush(stdout);
input_pending(2,1); /* sleep((unsigned) 1); */
Point = pnt;
CLine = save;
point_cursor();
return;
}
else if (code == 1)
{
matchp = Point;
Point = 0;
strcpy(buf, "Matches ");
skip_whitespace();
if ((matchp == Point) && prevline(&Number_One))
{
Point = 0;
strcat(buf, buffer_substring());
nextline(&Number_One);
Point = 0;
}
strcat(buf, buffer_substring());
message(buf);
}
Point = pnt;
CLine = save;
}
int goto_match()
{
char *p;
Line *save;
int pnt, code;
p = (char *) (CLine->data + Point);
if ((*p != ')') && (*p != '}') && (*p != ']')) return(0);
save = CLine;
pnt = Point;
code = find_matching(*p, -1, 1); /* -1 since we want to shif back 1 */
if (code == -1)
{
if (!IS_MINIBUFFER) msg_error("Mismatch!!");
CLine = save;
Point = pnt;
return(0);
}
return(1);
}
int newline()
{
int push = 0;
if (bolp() && (CLine->prev != NULL))
{
push = 1;
push_spot();
CLine = CLine->prev;
Point = 0;
eol();
}
split_line();
ins('\n');
if (push)
{
pop_spot();
return(1);
}
Point--;
forwchars(&Number_One);
return(1);
}
int previous_char_cmd()
{
int pnt;
Cursor_Motion = 1;
if (bobp())
{
msg_error(Top_Of_Buffer_Error);
return(0);
}
pnt = Point - 1;
backwchars(&Number_One);
Goal_Column = calculate_column();
return((pnt == -1) || Window->trashed);
}
/* Slang calls by reference so make this a pointer ! */
void insert_whitespace(int *n)
{
int tab = User_Vars.tab;
int c1, c2, i, k, nspace;
if ((nspace = *n) <= 0) return;
c1 = calculate_column() - 1;
c2 = c1 + nspace;
if (tab)
{
i = c1 / tab;
k = c2 / tab - i;
if (k) nspace = c2 - (i + k) * tab;
ins_char_n_times('\t', k);
}
ins_char_n_times(' ', nspace);
}
/* check from point to end of line looking for tabs */
int tabs_present(void)
{
unsigned char *p, *pmax;
if (!User_Vars.tab) return(0);
pmax = CLine->data + CLine->len;
p = CLine->data + Point;
while (p < pmax) if (*p++ == '\t') return(1);
return(0);
}
int delete_char_cmd()
{
int upd;
char ch;
if (eobp())
{
msg_error(End_Of_Buffer_Error);
return(0);
}
ch = *(CLine->data + Point);
if (FAST_NOT_OK)
{
del();
upd = 1;
}
else
{
fast_del();
tt_delete_char();
upd = 0;
}
return(upd);
}
int backward_delete_char_cmd()
{
char ch;
if (bobp())
{
msg_error(Top_Of_Buffer_Error);
return(0);
}
if (bolp())
{
backwchars(&Number_One);
del();
return(1);
}
ch = *(CLine->data + (Point - 1));
if (FAST_NOT_OK)
{
backwchars(&Number_One);
del();
return(1);
}
backwchars(&Number_One);
putc('\b',stdout);
Screen_Col--;
fast_del();
tt_delete_char();
return(0);
}
int backward_delete_char_untabify()
{
unsigned char *p;
int n;
p = CLine->data + (Point - 1);
/* note that short circuit is assumed to avoid seg fault */
if (!Point || bobp() || (*p != '\t') || !User_Vars.tab) return backward_delete_char_cmd();
n = calculate_column() - 1;
backwchars(&Number_One);
del();
n = n - calculate_column();
ins_char_n_times(' ', n);
return(1);
}
int previous_line_cmd()
{
int ret, gc;
if (CLine == CBuf->beg)
{
msg_error(Top_Of_Buffer_Error);
return(0