home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************\
- * *
- * editor.c -- this is a primitive graphics mode editor with word-wrap *
- * It can be used as a template for a graphics mode editor, but it is *
- * not certified bug-free, and anybody thinking of using this code *
- * should study it carefully, beta-test it thoroughly, and debug as *
- * appropriate. This code is presented here primarily for academic *
- * purposes: it is one approach to the problem of how to write a *
- * graphics mode text editor. *
- * *
- * Use this code freely, and send suggestions for optimizations and *
- * improvements to Diana Gruber. *
- * *
- \**********************************************************************/
-
- #include "defs.h"
-
- #define CTRL_Y 25
-
- #define F1 59
- #define F2 60
- #define F9 67
- #define F10 68
-
- #define CHAR_WIDTH 8
-
- int overstrike;
- int top_row, bottom_row;
-
- /**********************************************************************\
- * *
- * can_wrap -- is there enough room to do a word wrap? *
- * *
- \**********************************************************************/
-
- can_wrap(s1,s2,length)
- char *s1, *s2;
- int length;
- {
- if (strlen(s1)+strlen(s2) < length)
- return(TRUE);
- else
- return(FALSE);
- }
-
- /**********************************************************************\
- * *
- * clear_string -- clear all or part of a row of chars *
- * *
- \**********************************************************************/
-
- void clear_string(x,y,len,maxx)
- int x, y, len, maxx;
- {
- int x1, y0;
- int color;
-
- if (len == 0) return;
-
- y0 = y - ptsize;
- x1 = x + len * CHAR_WIDTH - 1;
- if (x1 > maxx) x1 = maxx;
-
- color = fg_getcolor();
- fg_setcolor(background);
- fg_rect(x,x1,y0,y);
- fg_setcolor(color);
- }
-
- /**********************************************************************\
- * *
- * editor -- edit nrows lines of text *
- * *
- \**********************************************************************/
-
- editor(array,minx,maxx,miny,maxy,nrows,array_len)
- char *array;
- int minx, miny, maxx, maxy, nrows;
- int *array_len;
- {
- register int i, n;
- int b, l;
- int x, y;
- int iy;
- unsigned char key, aux;
- static char char_string[] = {0,0};
- int maxcol;
- int row;
- char *tempstring;
- char *string[101];
- int col[101];
- int end[101];
- int color;
- int visible_rows;
-
- color = fg_getcolor();
- fg_setpage(visual);
- overstrike = FALSE;
- iy = miny + ptsize;
-
- /* determine the string size */
-
- maxcol = (maxx+1 - minx) / CHAR_WIDTH;
-
- /* allocate space for the strings and initialize all elements to 0 */
-
- for (n = 0; n < nrows; n++)
- {
- if ((string[n] = calloc(maxcol+3,sizeof(char))) == NULL)
- return(ERR);
- col[n] = 0;
- end[n] = 0;
- }
-
- tempstring = calloc(maxcol+2,sizeof(char));
-
- /* display whatever is in the array now */
-
- l = 0;
- x = minx;
- y = iy;
- top_row = 0;
- bottom_row = ((maxy - miny + 1) / (ptsize+1));
- if (bottom_row > nrows) bottom_row = nrows;
-
- /* recalc maxy based on ptsize, for scrolling */
-
- maxy = iy + 1 + (bottom_row-1) * (ptsize + 1);
-
- /* recalc nrows because they don't seem to come out right? */
-
- nrows++;
-
- for (row = top_row; row < bottom_row; row++)
- {
- put_string(&array[l],x,y);
- strcpy(string[row],&array[l]); /* copy it to the temp string */
- unblank(string[row]);
-
- l += strlen(&array[l]) + 1;
- col[row] = strlen(string[row]);
- y += ptsize + 1;
- }
-
- /* if there any rows beyond the bottom row */
-
- for (row = bottom_row; row<nrows; row++)
- {
- strcpy(string[row],&array[l]);
- l += strlen(&array[l]) + 1;
- unblank(string[row]);
- col[row] = strlen(string[row]);
- }
-
- flushkey();
-
- row = 0; /* starting position */
- col[row] = 0;
- x = get_x(minx,col[row]);
- y = iy;
- put_editor_cursor(x,y);
-
- visible_rows = bottom_row - top_row;
-
- while (TRUE)
- {
- fg_getkey(&key,&aux);
-
- /* return */
-
- if (key == CR)
- {
- unblank(string[row]);
- remove_editor_cursor(x,y);
- if (row < bottom_row - 1)
- {
- n = end_paragraph(row,string);
- if (n < bottom_row - 1)
- {
- for (i = n; i > row; i--)
- {
- strcpy(string[i+1],string[i]);
- y = get_y(iy,i+1);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[i+1],minx,y);
- }
- strcpy(string[row+1],&string[row][col[row]]);
- string[row][col[row]] = NULL;
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- clear_string(x,y,maxcol,maxx);
- y = get_y(iy,row+1);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[row+1],minx,y);
- }
- row++;
- }
- else if (bottom_row < nrows - 1)
- {
- fg_setcolor(background);
- fg_scroll(minx,maxx,(iy+1),maxy,-(ptsize+1),1);
- fg_setcolor(color);
- bottom_row++;
- top_row++;
- row++;
- y = get_y(iy,bottom_row-1);
- put_string(string[bottom_row-1],minx,y);
- }
- else
- row = top_row;
-
- col[row] = 0;
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
-
- /* F1 -- help screen */
-
- else if (aux == F1)
- {
- remove_editor_cursor(x,y);
- help_screen();
- fg_setcolor(15);
- put_editor_cursor(x,y);
- }
-
- /* back space */
-
- else if (key == BS && col[row] > 0)
- {
- remove_editor_cursor(x,y);
- col[row]--;
- string[row][col[row]] = NULL; /* remove a character */
-
- strcpy(tempstring,string[row]);
- strcat(tempstring,&string[row][col[row]+1]);
- strcpy(string[row],tempstring);
-
- x = get_x(minx,col[row]);
- clear_string(x,y,maxcol,maxx);
- put_string(&string[row][col[row]],x,y);
-
- put_editor_cursor(x,y);
- }
-
- /* delete */
-
- else if (aux == DELETE)
- {
- if (string[row][col[row]] == NULL && row < bottom_row-1)
- /* delete at end of line */
- {
- end[row] = strlen(string[row]);
- end[row+1] = strlen(string[row+1]);
-
- b = first_blank(string[row+1]);
- if (end[row] + b <= maxcol)
- {
- remove_editor_cursor(x,y);
-
- /* see if you can wrap more than one word */
-
- while (end[row]+b <= maxcol && b < end[row+1])
- {
- n = b;
- b += first_blank(&string[row+1][b+1]) + 1;
- }
- if (end[row]+b > maxcol) b = n;
-
- if (string[row+1][b] == NULL) /* wrap whole line */
- {
- strcat(string[row],string[row+1]); /* move all lines up */
-
- for (i = row+1; i < bottom_row; i++)
- {
- strcpy(string[i],string[i+1]);
- y = get_y(iy,i);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[i],minx,y);
- }
- for (i = bottom_row; i < nrows-1; i++)
- {
- strcpy(string[i],string[i+1]);
- }
- string[nrows-1][0] = NULL;
- }
- else /* wrap one word of several on next line */
- {
- string[row+1][b] = NULL;
- strcat(string[row],string[row+1]);
- strcpy(tempstring,&string[row+1][b+1]);
- strcpy(string[row+1],tempstring);
- y = get_y(iy,row+1);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[row+1],minx,y);
- }
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_string(&string[row][col[row]],x,y);
- put_editor_cursor(x,y);
- }
- continue;
- }
- else if (string[row][col[row]] != NULL)
- {
- string[row][col[row]] = NULL; /* remove a character */
-
- strcpy(tempstring,string[row]);
- strcat(tempstring,&string[row][col[row]+1]);
- strcpy(string[row],tempstring);
-
- clear_string(x,y,maxcol,maxx);
- put_string(&string[row][col[row]],x,y);
- }
- }
-
- /* line delete -- ctrl y */
-
- else if (key == CTRL_Y)
- {
- col[row] = 0;
- string[row][col[row]] = NULL;
- remove_editor_cursor(x,y);
- x = minx;
- clear_string(x,y,maxcol,maxx);
- put_editor_cursor(x,y);
- }
-
- /* left arrow */
-
- else if (aux == LEFT_ARROW)
- {
- if (col[row] > 0)
- {
- remove_editor_cursor(x,y);
- col[row]--;
- x = get_x(minx,col[row]);
- put_editor_cursor(x,y);
- }
- else if (row > 0)
- {
- remove_editor_cursor(x,y);
- row--;
- end[row] = strlen(string[row]);
- col[row] = MIN(end[row],maxcol-1);
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- }
-
- /* right arrow */
-
- else if (aux == RIGHT_ARROW)
- {
- if (col[row] < maxcol-1)
- {
- if (string[row][col[row]] == NULL)
- {
- string[row][col[row]] = 32;
- string[row][col[row]+1] = NULL;
- }
- remove_editor_cursor(x,y);
- col[row]++;
- x = get_x(minx,col[row]);
- put_editor_cursor(x,y);
- }
- else if (row < bottom_row-1)
- {
- remove_editor_cursor(x,y);
- row++;
- col[row] = 0;
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- }
-
- /* up arrow */
-
- else if (aux == UP_ARROW)
- {
- if (row > top_row)
- {
- unblank(string[row]);
- remove_editor_cursor(x,y);
- row--;
- end[row] = strlen(string[row]);
- col[row] = MIN(end[row],col[row+1]);
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- else if (top_row > 0)
- {
- unblank(string[row]);
- remove_editor_cursor(x,y);
-
- end[row] = strlen(string[row]);
- col[row] = 0;
-
- bottom_row--;
- top_row--;
- row--;
-
- fg_setcolor(background);
- fg_scroll(minx,maxx,miny-1,maxy-ptsize-3,ptsize+1,1);
- fg_setcolor(color);
-
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_string(string[row],minx,y);
- put_editor_cursor(x,y);
- }
- }
-
- /* down arrow */
-
- else if (aux == DOWN_ARROW)
- {
- if (row < bottom_row-1)
- {
- unblank(string[row]);
- remove_editor_cursor(x,y);
- row++;
- end[row] = strlen(string[row]);
- col[row] = MIN(end[row],col[row-1]);
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- else if (bottom_row < nrows-1)
- {
- unblank(string[row]);
- remove_editor_cursor(x,y);
-
- bottom_row++;
- top_row++;
- row++;
-
- end[row] = strlen(string[row]);
- col[row] = MIN(end[row],col[row-1]);
-
- fg_setcolor(background);
- fg_scroll(minx,maxx,iy+1,maxy,-(ptsize+1),1);
- fg_setcolor(color);
-
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_string(string[row],minx,y);
- put_editor_cursor(x,y);
- }
-
- }
-
- /* PgUp */
-
- else if (aux == PAGE_UP && row > 0)
- {
- if (top_row > visible_rows)
- {
- top_row -= visible_rows;
- bottom_row -= visible_rows;
- }
- else
- {
- top_row = 0;
- bottom_row = visible_rows;
- }
-
- fg_setcolor(background);
- fg_rect(minx,maxx,miny,maxy);
- fg_setcolor(color);
-
- for (row = top_row; row < bottom_row; row++)
- {
- y = get_y(iy,row);
- put_string(string[row],minx,y);
- }
-
- row = top_row;
-
- end[row] = strlen(string[row]);
- col[row] = 0;
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
-
- /* PgDn */
-
- else if (aux == PAGE_DOWN)
- {
- if (bottom_row < nrows-visible_rows)
- {
- top_row += visible_rows;
- bottom_row += visible_rows;
- }
- else
- {
- top_row = nrows - visible_rows - 1;
- bottom_row = nrows - 1;
- }
-
- fg_setcolor(background);
- fg_rect(minx,maxx,miny,maxy);
- fg_setcolor(color);
-
- for (row = top_row; row < bottom_row; row++)
- {
- y = get_y(iy,row);
- put_string(string[row],minx,y);
- }
-
- row = top_row;
-
- end[row] = strlen(string[row]);
- col[row] = 0;
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
-
- /* home */
-
- else if (aux == HOME)
- {
- remove_editor_cursor(x,y);
- col[row] = 0;
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
-
- /* end */
-
- else if (aux == END)
- {
- remove_editor_cursor(x,y);
- unblank(string[row]);
- end[row] = strlen(string[row]);
- col[row] = MIN(end[row],maxcol-1);
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
-
- /* insert toggles insert mode */
-
- else if (aux == INSERT)
- {
- overstrike = !overstrike;
- put_editor_cursor(x,y);
- }
- /* esc or F10 to return */
-
- else if (aux == F10 || key == ESC)
- break;
-
- /* printable character -- insert mode */
-
- if ((is_char(key) || key == SPACEBAR) && !overstrike)
- {
- l = 0;
- remove_editor_cursor(x,y);
-
- strcpy(tempstring,&string[row][col[row]]);
- string[row][col[row]] = key;
- string[row][col[row]+1] = NULL;
- strcat(string[row],tempstring);
- end[row] = strlen(string[row]);
-
- /* row too long, must wrap */
-
- if (end[row] > maxcol || col[row] == maxcol-1)
- {
- if (row == bottom_row-1 && bottom_row < nrows-1)
- {
- fg_setcolor(background);
- fg_scroll(minx,maxx,iy+1,maxy,-(ptsize+1),1);
- fg_setcolor(color);
- bottom_row++;
- top_row++;
- y = get_y(iy,row+1);
- put_string(string[row+1],minx,y);
- }
-
- if (row < bottom_row-1)
- {
- b = last_blank(string[row]) + 1;
- if (can_wrap(&string[row][b],string[row+1],maxcol))
- {
-
- l = b - col[row];
- word_wrap(&string[row][b],string[row+1]);
- string[row][b] = NULL;
- unblank(string[row]);
- unblank(string[row+1]);
-
- /* redraw the second row of text */
-
- y = get_y(iy,row+1);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[row+1],minx,y);
-
- /* recalc cursor position */
-
- if (col[row] >= b) /* cursor is in word that gets wrapped */
- {
- /* erase last word of row */
-
- x = get_x(minx,b);
- y = get_y(iy,row);
- clear_string(x,y,maxcol,maxx);
-
- row++;
- col[row] = col[row-1] - b;
- unblank(string[row]);
- }
- else /* cursor stays on current line */
- {
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- clear_string(x,y,maxcol,maxx);
- put_string(&string[row][col[row]],x,y);
- }
- }
- else /* can't wrap: shorten string */
- {
- string[row][maxcol] = NULL;
- y = get_y(iy,row);
- clear_string(x,y,maxcol,maxx);
- put_string(&string[row][col[row]],x,y);
- }
-
- if (col[row] < maxcol-1)
- col[row]++;
- else if (row < bottom_row)
- {
- row++;
- col[row] = 0;
- unblank(string[row]);
- }
-
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- else /* row = bottom_row-1 */
- {
- string[row][maxcol] = NULL;
- clear_string(x,y,maxcol,maxx);
- y = get_y(iy,row);
- put_string(&string[row][col[row]],x,y);
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- }
-
- else /* wrapping not necessary */
-
- {
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- clear_string(x,y,maxcol,maxx);
- put_string(&string[row][col[row]],x,y);
-
- end[row] = strlen(string[row]);
-
- if (col[row] <= end[row]+1 && col[row] < maxcol-1)
- col[row]++;
- else if (row < bottom_row-1)
- {
- row++;
- col[row] = l;
- }
- else
- {
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- string[row][maxcol] = NULL;
- clear_string(x,y,maxcol,maxx);
- put_string(&string[row][col[row]],x,y);
- }
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- }
-
- /* printable character -- overstrike mode */
-
- else if ((is_char(key) || key == SPACEBAR) && overstrike)
- {
- remove_editor_cursor(x,y);
- string[row][col[row]] = key;
- char_string[0] = key;
- clear_string(x,y,1,maxx);
- put_string(char_string,x,y);
-
- if (col[row] < maxcol-1)
- col[row]++;
-
- /* trying to write a character past the end of a row, must wrap */
-
- else if (row < bottom_row-1)
- {
- b = last_blank(string[row])+1;
- l = strlen(&string[row][b]);
- unblank(string[row+1]);
- if (can_wrap(&string[row][b],string[row+1],maxcol))
- {
- word_wrap(&string[row][b],string[row+1]);
- string[row][b] = NULL;
-
- /* redraw the two rows of text */
-
- y = get_y(iy,row);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[row],minx,y);
-
- row++;
- unblank(string[row]);
-
- y = get_y(iy,row);
- clear_string(minx,y,maxcol,maxx);
- put_string(string[row],minx,y);
-
- col[row] = l;
-
- }
- else
- {
- row++;
- col[row] = 0;
- unblank(string[row]);
- }
- }
-
- x = get_x(minx,col[row]);
- y = get_y(iy,row);
- put_editor_cursor(x,y);
- }
- }
-
- /* end while */
-
- l = 0; /* put all the strings in one array */
- for (n = 0; n < nrows; n++) /* separated by nulls */
- {
- strcpy(&array[l],string[n]);
- l += strlen(string[n]) + 1;
- free (string[n]); /* free the temporary arrays */
- array[l] = 0;
- l++;
- }
-
- *array_len = l;
-
- free(tempstring);
- return(OK);
- }
-
- /**********************************************************************\
- * *
- * end_paragraph -- find the first blank line after a line of text *
- * *
- \**********************************************************************/
-
- end_paragraph(row,string)
- char *string[60];
- int row;
- {
- register int n;
-
- for (n = row+1; n < 60; n++)
- {
- unblank(string[n]);
- if (string[n][0] == NULL)
- break;
- }
- n--;
- return(n);
- }
-
- /**********************************************************************\
- * *
- * first_blank -- find the first blank space before the end of a string *
- * *
- \**********************************************************************/
-
- first_blank(s)
- char *s;
- {
- register int i;
- int nchar;
-
- nchar = strlen(s);
-
- i = 0;
- while (i <= nchar && is_char(s[i]))
- i++;
-
- /* return value of blank */
-
- return(i);
- }
-
- /**********************************************************************\
- * *
- * get_x -- calculate the x position based on row and column *
- * *
- \**********************************************************************/
-
- get_x(x,col)
- int x, col;
- {
- return(x + col * CHAR_WIDTH);
- }
-
- /**********************************************************************\
- * *
- * get_y -- calculate the y position based on row and column *
- * *
- \**********************************************************************/
-
- get_y(y,row)
- int y, row;
- {
- return(y + (row-top_row) * (ptsize+1));
- }
-
- /**********************************************************************\
- * *
- * help_screen -- display keystroke help *
- * *
- \**********************************************************************/
-
- void help_screen()
- {
- register int i;
- unsigned char key, aux;
-
- static char string[13][50] = {
- " Arrows: move the cursor around",
- " Del: delete a letter",
- " Ctrl-Y: delete the whole line",
- " Home: go to beginning of line",
- " End: go to end of line",
- " PgUp: go up one screen",
- " PgDn: go down one screen",
- " Enter: go to the next line",
- " Ins: insert or overstrike" ,
- " Esc: done editing" ,
- " "
- " press any key to exit help"
- };
-
- static int line [] = {46,58,70,82,94,106,118,130,142,154,166,182};
-
- fg_save(10,309,25,189);
-
- background = 2;
- fg_setcolor(2);
- fg_rect(10,309,25,189);
- fg_setcolor(15);
- draw_box(11,308,26,188);
-
- for (i = 0; i < 12; i++)
- {
- put_string(string[i],14,line[i]);
- }
- fg_getkey(&key,&aux);
- fg_restore(10,309,25,189);
- background = 0;
- }
-
- /**********************************************************************\
- * *
- * is_char -- is it a legitimate character that we can display? *
- * *
- \**********************************************************************/
-
- is_char(c)
- char c;
- {
- if (c > 32 && c <= 126)
- return(TRUE);
- else
- return(FALSE);
- }
-
- /**********************************************************************\
- * *
- * last_blank -- find the last blank space before the end of a string *
- * *
- \**********************************************************************/
-
- last_blank(s)
- char *s;
- {
- register int i;
-
- /* find the end of the string */
-
- for (i = 0; s[i]; i++)
- ;
-
- /* count backwards, finding the blank */
-
- while (i > 0 && is_char(s[i-1]))
- i--;
-
- i--; /* next character back must be non-alpha */
-
- /* return value of blank */
-
- return(i);
- }
-
- /**********************************************************************\
- * *
- * put_editor_cursor -- put a cursor under where the next char goes *
- * *
- \**********************************************************************/
-
- void put_editor_cursor(x,y)
- int x, y;
- {
- int color;
-
- color = fg_getcolor();
-
- if (mode06 || mode11)
- fg_setcolor(1);
- else if (overstrike)
- fg_setcolor(2);
- else
- fg_setcolor(14);
-
- fg_move(x,y+1);
- fg_draw(x+8,y+1);
- fg_setcolor(color);
- }
-
- /**********************************************************************\
- * *
- * remove_editor_cursor -- delete the cursor from its current position *
- * *
- \**********************************************************************/
-
- void remove_editor_cursor(x,y)
- int x, y;
- {
- int color;
-
- color = fg_getcolor();
- fg_setcolor(background);
- fg_move(x,y+1);
- fg_draw(x+8,y+1);
- fg_setcolor(color);
- }
-
- /**********************************************************************\
- * *
- * unblank -- remove trailing blanks and other garbage from a string *
- * *
- \**********************************************************************/
-
- void unblank(s)
- char *s;
- {
- register int i;
-
- /* find the end of the string */
-
- for (i = 0; s[i]; i++)
- ;
-
- /* count back trailing spaces */
-
- while (i > 0 && !is_char(s[i-1]))
- i--;
-
- /* set new end of string */
-
- s[i] = '\0';
- }
-
- /**********************************************************************\
- * *
- * word_wrap -- take the last word of one string, put at beginning of *
- * next string. *
- * *
- \**********************************************************************/
-
- void word_wrap(s1,s2)
- char *s1, *s2;
- {
- char tempstring[60];
-
- strcpy(tempstring,s1);
- strcat(tempstring," ");
- strcat(tempstring,s2);
- strcpy(s2,tempstring);
- }