home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "externs.h"
- #include "window.h"
- #include "line.h"
- #include "display.h"
-
- Window *WIN;
- Window *TOP_WIN;
- int COLUMN = 1;
- int BEEP_MINI_B = 0;
- int MINIBUFFER_SELECTED = 0;
- int CURS_ROW;
- int CURS_COL;
- int RESTORE_WIDTH_TO = 0;
- unsigned char *CURS_POS;
-
- int read_string(char *str)
- {
- char ch;
- int i;
-
- i = strlen(str);
- do
- {
- ch = getkey();
- if ((ch == '\b') || (ch == 127))
- {
- if (i > 0)
- {
- if (str[--i] < 32) fputs("\b \b",stdout); /* erase the ^ */
- fputs("\b \b",stdout);
- }
- else fputc('\007',stdout);
- }
- else if ((ch < 32) && (ch != 10) && (ch != 13))
- {
- if ((ch == '\007') || (ch == '\025')) /* ^G or ^U aborts */
- {
- fputc('\007',stdout);
- return(-1); /* ^G quits */
- }
- if (ch == '\033') /* Allow KP ENTER as a terminator */
- {
- ch = getkey();
- if (ch == 'O')
- {
- ch = getkey();
- if (ch == 'M')
- {
- str[i] = '\0';
- return(i);
- }
- else
- {
- fputc('^',stdout);
- fputc('[',stdout);
- fputc(str[i++] = 'O', stdout);
- fputc(str[i++] = ch, stdout);
- }
- }
- else
- {
- fputc('^',stdout);
- fputc('[',stdout);
- fputc(str[i++] = ch, stdout);
- }
- }
- else
- {
- str[i++] = ch;
- fputc('^',stdout);
- fputc(ch + '@',stdout);
- }
- }
- else if (ch == '`') /* quoted insert */
- {
- ch = getkey();
- str[i++] = ch;
- if ((ch < ' ') || (ch == 127))
- {
- if (ch == 127) ch = '?'; else ch = ch + '@';
- fputc('^',stdout);
- }
- fputc(ch,stdout);
- }
- else if ((ch != 10) && (ch != 13))
- {
- str[i++] = ch;
- fputc(ch,stdout);
- }
-
- fflush(stdout);
- }
- while ((ch != 10) && (ch != 13));
-
- str[i] = '\0';
- return(i);
- }
-
-
- void message(char *what, int how)
- {
- strcpy(MINI_BUF,what);
- if (how) BEEP_MINI_B = 1; else BEEP_MINI_B = 0;
- }
-
- void select_minibuffer()
- {
- if (MINIBUFFER_SELECTED) return;
- MINIBUFFER_SELECTED = 1;
- set_scroll_region(1,SCREEN_HEIGHT);
- goto_rc(SCREEN_HEIGHT,1);
- fflush(stdout);
- }
-
- void exit_minibuffer()
- {
- if (!MINIBUFFER_SELECTED) return;
- MINIBUFFER_SELECTED = 0;
- set_scroll_region(WIN->top,WIN->bot);
- fflush(stdout);
- }
-
- /* put out string, expanding control chars */
- void nicely_puts(char *str, FILE *fp)
- {
- while (*str != '\0')
- {
- if ((*str < ' ') || (*str == 127))
- {
- fputc('^',fp);
- if (*str != 127) fputc(*str + '@',fp); else fputc('?',fp);
- }
- else fputc(*str,fp);
- str++;
- }
- }
-
- void put_message()
- {
- select_minibuffer();
- delete_line(1);
- if (BEEP_MINI_B) fputc('\007',stdout);
- BEEP_MINI_B = 0;
- if (*MINI_BUF != '\0') nicely_puts((char *) MINI_BUF, stdout);
- exit_minibuffer();
- }
-
- /* puts 'what in the minibuffer to be edited. */
- /* returns number of chars read */
- int read_from_minibuffer(char *prompt, char *what)
- {
- int i;
- char str[132];
-
- select_minibuffer();
- fputs(prompt,stdout);
- if (*what != '\0')
- nicely_puts(what,stdout);
- fflush(stdout);
- strcpy(str,what);
- i = read_string(str);
- if (i > 0) strcpy(what,str);
- delete_line(1);
- exit_minibuffer();
- return(i);
- }
-
-
- void clear_minibuffer()
- {
- MINI_BUF[0] = '\0';
- BEEP_MINI_B = 0;
- put_message();
- }
-
-
- int get_scroll(int *line)
- {
- /* line is the line we want at the topo of the window if possible */
- int dtop, dbot,n,top,bot,wsize;
-
- top = WIN->beg_line;
- wsize = WIN->bot - WIN->top; /* actually 1 less than window size */
- bot = top + wsize;
-
- if ((*line == 1) && (top == 1))
- {
- message("Top of Buffer.",1);
- return(0);
- }
-
- /* handles endof file in a window */
- if ((bot > NUM_LINES) && *line > C_LINE)
- {
- *line = top;
- message("End of Buffer.",1);
- return(0);
- }
-
- if (NUM_LINES <= wsize) /* short file */
- {
- *line = 1;
- return(0);
- }
-
- dtop = top - 1;
- dbot = NUM_LINES - bot;
- n = *line - top;
-
- if ((n>0) && (dbot < n))
- {
- n = dbot;
- *line = top + n;
- if (!n) message("End of buffer.",1);
- }
- else if ((n < 0) && (dtop + n < 0))
- {
- n = -dtop;
- if (!n) message("Top of buffer.",1);
- *line = n + top;
- }
- return(n);
- }
-
-
- void update_window(int line)
- {
- int n,max_n, save_line, save_col, npos;
- unsigned char *save_pos;
-
- if (COLUMN != WIN->col)
- {
- if (COLUMN < 1) COLUMN = 1;
- if (COLUMN != WIN->col)
- {
- save_pos = CURS_POS; save_line = CURS_ROW; save_col = CURS_COL;
- redraw_window();
- update_status(0);
- WIN->curs_pos = CURS_POS = save_pos;
- WIN->curs_line = CURS_ROW = save_line;
- WIN->curs_col = CURS_COL = save_col;
- }
- return;
- }
-
-
- n = get_scroll(&line);
- max_n = WIN->bot - WIN->top;
- if (abs(n) > max_n)
- {
- goto_line(line);
- redraw_window();
- update_status(0);
- return;
- }
- if (!n) return;
-
- goto_rc(1,1);
- forward_line(n);
- WIN->beg_pos = C_POS;
- WIN->beg_line = C_LINE;
-
- if (n>0)
- {
- npos = 1;
- delete_nlines(n);
- goto_rc(WIN->bot - WIN->top - n + 2,1);
- forward_line(max_n - n + 1);
- }
- else
- {
- npos = 0;
- CURS_ROW = 1; CURS_COL = 1; CURS_POS = C_POS;
- n = -n;
- reverse_index(n);
- }
- n = n - 1;
- display_line();
- while(n--)
- {
- forward_line(1);
- fputc('\n',stdout);
- display_line();
- }
- if (npos)
- {
-
- CURS_ROW = C_LINE - WIN->beg_line + 1;
- CURS_COL = 1; CURS_POS = C_POS;
- }
-
- C_POS = WIN->beg_pos;
- C_LINE = WIN->beg_line;
- update_status(0);
- fflush(stdout);
- }
-
- /* updates current window as well as scroll lock ones */
- /* Although current window is update in an absolute fashion, scroll locked
- ones are updated in a relative fashion */
- void update_windows(int line)
- {
- int dline,flg;
- Window *w;
-
- dline = line - C_LINE;
- update_window(line);
- if (!WIN->lock) return;
- flg = 0;
- w = WIN;
- while(WIN = WIN->next, WIN != w)
- {
- if (WIN->lock)
- {
- flg = 1;
- set_window(WIN);
- line = C_LINE + dline;
- update_window(line);
- }
- }
- WIN = w;
- if (flg) set_window(WIN);
- }
-
-
- void redraw_window()
- {
- int n,t;
- t = WIN->top;
- if (t == 1) clear_window();
- goto_rc(1, 1);
- n = WIN->bot - WIN->top;
- if ((C_LINE + n) > NUM_LINES) goto_line(NUM_LINES - n);
- WIN->curs_pos = CURS_POS = WIN->beg_pos = C_POS;
- WIN->beg_line = C_LINE;
- WIN->col = COLUMN;
- WIN->curs_col = CURS_COL = 1;
- WIN->curs_line = CURS_ROW = 1;
- if (t != 1) delete_line(1);
- display_line();
- while(n--)
- {
- fputc('\n',stdout);
- if (t != 1) delete_line(1);
- if (forward_line(1)) display_line();
- }
-
-
- C_POS = WIN->beg_pos;
- C_LINE = WIN->beg_line;
- }
-
- /* associates current window with current buffer */
- void save_win_flags(Window *w)
- {
- w->flags = 0;
- if (MOST_V_OPT) w->flags |= _MOST_V_OPT;
- if (MOST_B_OPT) w->flags |= _MOST_B_OPT;
- if (MOST_T_OPT) w->flags |= _MOST_T_OPT;
- if (MOST_W_OPT) w->flags |= _MOST_W_OPT;
- if (SQUEEZE_LINES) w->flags |= _MOST_SQ_OPT;
- w->n_lines = NUM_LINES;
- w->display = MOST_S_OPT;
- }
-
- void window_buffer()
- {
- WIN->beg_line = C_LINE;
- WIN->beg_pos = C_POS;
- WIN->col = COLUMN;
- WIN->buf = BUF;
- MOST_S_OPT = 0;
- save_win_flags(WIN);
- }
-
- void clear_window()
- {
- int i,n;
- i = WIN->top;
- n = WIN->bot - WIN->top;
- if (i == 1)
- {
- goto_rc(WIN->bot - WIN->top + 1,SCREEN_WIDTH);
- clr_bos();
- }
- else
- {
- goto_rc(i - WIN->top + 1,1);
- delete_line(1);
- while(n--)
- {
- fputc('\n',stdout);
- delete_line(1);
- }
- }
-
- goto_rc(i - WIN->top + 1,1);
- fflush(stdout);
- }
-
- void restore_win_flags()
- {
- MOST_V_OPT = WIN->flags & _MOST_V_OPT;
- MOST_B_OPT = WIN->flags & _MOST_B_OPT;
- MOST_T_OPT = WIN->flags & _MOST_T_OPT;
- MOST_W_OPT = WIN->flags & _MOST_W_OPT;
- SQUEEZE_LINES = WIN->flags & _MOST_SQ_OPT;
- NUM_LINES = WIN->n_lines;
- MOST_S_OPT = WIN->display;
- }
-
-
- Window *make_window(int r1,int r2)
- {
- int i;
- Window *new;
- new = (Window *) malloc(sizeof(Window));
- new->status = (char *) malloc(135);
- for (i = 0; i <= SCREEN_WIDTH; i++) new->status[i] = '\0';
- new->col = COLUMN;
- new->top = r1;
- new->bot = r2;
- new->lock = 0;
- save_win_flags(new);
- return(new);
- }
-
- void init_display()
- {
- int i;
- fputs("\033[?6h",stdout);
- TOP_WIN = WIN = make_window(1,SCREEN_HEIGHT - 2);
- WIN->prev = WIN->next = WIN;
- cls();
- set_scroll_region(WIN->top, WIN->bot);
- goto_rc(1,1);
- fflush(stdout);
- }
-
- void reset_display()
- {
- set_scroll_region(1,SCREEN_HEIGHT);
- fputs("\033[?6l",stdout); /* normal origin mode */
- goto_rc(SCREEN_HEIGHT,1);
- if (RESTORE_WIDTH_TO)
- {
- set_width(RESTORE_WIDTH_TO, 0);
- RESTORE_WIDTH_TO = 0;
- }
-
- fflush(stdout);
- }
-
- update_status1(int new_status)
- {
- char str[30], ch, *strp;
- static char new[135];
- int i,ii,r,x,line_p = 60;
-
- r = WIN->bot + 1;
- goto_rc(r,1);
-
- i = ii = 0;
- new[ii++] = '-';
- if (WIN->lock) new[ii++] = '*'; else new[ii++] = '-';
- strp = " MOST: ";
- while(*strp != '\0') new[ii++] = *strp++;
-
- while(ch = WIN->buf->file[i++], ch != '\0') new[ii++] = ch;
-
- while(ii < line_p) new[ii++] = ' ';
-
- x = (C_LINE + WIN->bot - WIN->top) * 100; x = x / NUM_LINES;
-
- /* for files with end of file above the bottom row (due to window manipulations) */
- if (x > 100) x = 100;
- sprintf(str,"(%d,%d) %d%%",C_LINE,COLUMN,x);
- i = 0; while(ch = str[i++], ch != '\0') new[ii++] = ch;
-
- while(ii < SCREEN_WIDTH) new[ii++] = '-';
- new[SCREEN_WIDTH] = '\0';
- set_attribute(7);
- if (new_status)
- fputs(new,stdout);
- else
- smart_puts(new,WIN->status,stdout);
- set_attribute(0);
- strcpy(WIN->status,new);
- }
-
- void update_status(int new_status)
- {
-
- C_LINE = WIN->beg_line;
- C_POS = WIN->beg_pos;
- set_scroll_region(1,SCREEN_HEIGHT);
- update_status1(new_status);
- set_scroll_region(WIN->top,WIN->bot);
- fflush(stdout);
- }
-
- /* splits window-- no screen update, does not affect scrolling region */
- int split_window()
- {
- Window *new, *old;
- int b2,t2,b1, line;
-
- b2 = WIN->bot;
- b1 = (WIN->bot + WIN->top) / 2 - 1;
- t2 = b1 + 2;
- if ((b1 == WIN->top) || (t2 == b2)) return(0);
-
- /* line is top line of new window. */
- line = WIN->beg_line + t2 - WIN->top;
- old = WIN;
- WIN->bot = b1;
- new = make_window(t2,b2);
- /* add to ring */
- WIN->next->prev = new;
- new->next = WIN->next;
- new->prev = WIN;
- WIN->next = new;
-
- new->beg_line = line;
- new->buf = BUF;
- /* new window status line is at same position as old */
- strcpy(new->status,WIN->status);
- return(1);
- }
-
-
- void two_windows()
- {
- int line;
- Window *new, *old;
- if (!split_window()) return;
-
- old = WIN;
- new = WIN->next;
- line = new->beg_line;
- if (line + new->bot - new->top > NUM_LINES)
- {
- other_window(1);
- /* since split window left new window undefined... */
- C_POS = old->beg_pos;
- C_LINE = old->beg_line;
- if (NUM_LINES <= new->bot - new->top + 1)
- {
- C_LINE = new->beg_line = 1;
- C_POS = new->beg_pos = BUF->beg;
- redraw_window();
- update_status(0);
- }
- else if (line > NUM_LINES)
- {
- goto_line(NUM_LINES - new->bot + new->top);
- WIN->beg_pos = C_POS;
- WIN->beg_line = C_LINE;
- redraw_window();
- update_status(0);
- }
- else
- {
- goto_line(line);
- WIN->beg_pos = C_POS;
- WIN->beg_line = C_LINE;
- update_window(NUM_LINES - new->bot + new->top);
- }
- WIN->curs_line = 1;
- WIN->curs_col = COLUMN;
- WIN->curs_pos = C_POS;
- other_window(-1);
- }
- else
- {
- WIN = new;
- (void) forward_line(line - old->beg_line);
- new->beg_pos = C_POS;
- new->beg_line = C_LINE;
- new->curs_line = 1;
- new->curs_col = COLUMN;
- new->curs_pos = C_POS;
- update_status(0);
- WIN = old;
- }
- update_status(1);
- }
-
- void expand_window1(int dn)
- {
- int l, save_top, save_line;
- unsigned char *save_pos;
-
- /* l is line after last line of current window (where status line is) */
- l = WIN->beg_line + WIN->bot - WIN->top + 1;
- save_top = WIN->top;
- WIN->top = WIN->bot + 1;
- WIN->bot = WIN->bot + dn;
- set_scroll_region(WIN->top, WIN->bot);
- if (l > NUM_LINES)
- {
- clear_window();
- }
- else
- {
- /* should add something here for smarter scrolling...
- if ((WIN->next->BUF == BUF) && (l >= WIN->next->beg_line)
- && (l <= (WIN->next->beg_line + WIN->next)
- */
-
- save_line = C_LINE;
- save_pos = C_POS;
- goto_line(l);
- redraw_window();
- WIN->beg_line = C_LINE = save_line;
- WIN->beg_pos = C_POS = save_pos;
- }
- WIN->top = save_top;
- set_scroll_region(WIN->top, WIN->bot);
- }
-
- void one_window()
- {
- Window *w, *tmp;
- int diff;
-
- if (WIN->next == WIN) return;
- w = WIN;
- WIN = WIN->next;
- /* delete other windows preserving the ring! */
- while(WIN != w)
- {
- free_window_buffer(); /* needs a ring */
- tmp = WIN->next;
- /* if this is the bottom window, save its status line */
- if (tmp == TOP_WIN) strcpy(w->status,WIN->status);
- tmp->prev = WIN->prev;
- WIN->prev->next = tmp;
- free(WIN);
- WIN = tmp;
- }
- WIN = w;
- /* slide the window to the top and expand it */
- diff = WIN->top - 1;
- if (diff)
- {
- set_scroll_region(1,SCREEN_HEIGHT - 2);
- goto_rc(1,1);
- delete_nlines(diff);
- WIN->top = 1;
- WIN->bot -= diff;
- TOP_WIN = WIN;
- }
- expand_window1(SCREEN_HEIGHT - 2 - WIN->bot);
- update_status(0);
- }
-
-
- void set_window(Window *w)
- {
- WIN = w;
- CURS_ROW = WIN->curs_line;
- CURS_COL = WIN->curs_col;
- CURS_POS = WIN->curs_pos;
- C_LINE = WIN->beg_line;
- C_POS = WIN->beg_pos;
- COLUMN = WIN->col;
- BUF = WIN->buf;
- switch_to_buffer(BUF);
- set_scroll_region(WIN->top,WIN->bot);
- restore_win_flags();
- fflush(stdout);
- }
-
- void other_window(int n)
- {
- if (!n) return;
- WIN->beg_pos = C_POS;
- WIN->curs_pos = CURS_POS;
- WIN->curs_line = CURS_ROW;
- WIN->curs_col = CURS_COL;
- WIN->beg_line = C_LINE;
- save_win_flags(WIN);
- if (n < 0)
- while (n++) WIN = WIN->prev;
- else
- while (n--) WIN = WIN->next;
- set_window(WIN);
- }
-
-
-
- /* kills window by moving lower window up */
- delete_as_top_window()
- {
- int t1,t2,b1,b2;
- t1 = WIN->top;
- t2 = WIN->next->top;
- b1 = WIN->bot;
- b2 = WIN->next->bot;
- WIN->prev->next = WIN->next;
- WIN->next->prev = WIN->prev;
-
- /* scroll contents of window below to top */
- set_scroll_region(t1,b2);
- goto_rc(1,1);
- delete_nlines(t2 - t1);
- other_window(1);
- WIN->top = t1;
- WIN->bot = b2 - t2 + t1;
- expand_window1(b2 - WIN->bot);
- update_status(0);
- }
-
- /* free buffer for this window if no other windows are viewing it. */
- free_window_buffer()
- {
- Window *w;
- int f = 1;
- w = WIN;
- WIN = w->next;
- while((WIN != w) && f)
- {
- if (!strcmp(WIN->buf->file,w->buf->file)) f = 0;
- WIN = WIN->next;
- }
- WIN = w;
- if (f) free(WIN->buf);
- }
-
-
- delete_window()
- {
- int new_b, old_b;
- Window *w;
-
- w = WIN;
- if (WIN->next == WIN) return;
- free_window_buffer();
- if (WIN->next != TOP_WIN)
- {
- if (WIN == TOP_WIN)
- {
- delete_as_top_window();
- TOP_WIN = WIN; /* not anymore, this one is */
- }
- else
- delete_as_top_window();
-
- free(w);
- return;
- }
- old_b = WIN->top - 2;
- new_b = WIN->bot;
- other_window(-1);
- expand_window1(new_b - old_b);
- strcpy(WIN->status,w->status); /* share the same line */
-
- WIN->next = w->next;
- WIN->next->prev = WIN;
- free(w);
- update_status(0);
- }
-
- void redraw_display()
- {
- Window *w;
- int n,t;
- fputs("\033[?6h",stdout); /* relative origins */
- set_scroll_region(1,SCREEN_HEIGHT);
- cls();
- save_win_flags(WIN);
- w = WIN;
- do
- {
- WIN = WIN->next;
- t = WIN->top;
- goto_rc(t, 1);
- C_POS = WIN->beg_pos;
- C_LINE = WIN->beg_line;
- COLUMN = WIN->col;
- switch_to_buffer(WIN->buf);
- restore_win_flags();
- n = WIN->bot - WIN->top;
- display_line();
- while(n--)
- {
- fputc('\n',stdout);
- if (forward_line(1)) display_line();
- }
- C_LINE = WIN->beg_line;
- C_POS = WIN->beg_pos;
- update_status1(1);
- }
- while(WIN != w);
- set_window(w);
- }
-
- void toggle_lock()
- {
- WIN->lock = !(WIN->lock);
- update_status(0);
- }
-