_TEXT EDITORS: ALGORITHMS AND ARCHITECTURES_ by Ray Valdes [LISTING ONE] /* EditLine() -- The simplest text editing routine */ void EditLine(char* buffer, int max_length, int curr_row) { int c, str_length = strlen(buffer), curr_column = str_length, insert_mode = TRUE; ChangeCursorShape(insert_mode); do { vt_ClearLineAt(curr_row,0); vt_OutputStringAt(buffer, curr_row,0); vt_SetCursorPositionAt(curr_row,curr_column); switch(c = vt_GetKeystroke()) /* dispatch on user's keystroke */ { /*-------- keystrokes that terminate the editing session-----*/ case ESCAPE_KEY: case ENTER_KEY: break; /*--------- keystrokes that merely change the cursor position---*/ case HOME_KEY: curr_column = 0; break; case END_KEY: curr_column = str_length; break; case LEFT_KEY: if (curr_column > 0) curr_column--; break; case RIGHT_KEY: if (curr_column < str_length) curr_column++; break; case INSERT_KEY: insert_mode = !insert_mode; ChangeCursorShape(insert_mode); break; /*------ keystrokes that alter the contents of the buffer----*/ case BACKSPACE_KEY: if (curr_column > 0) { movmem( &buffer[curr_column], /*source*/ &buffer[curr_column-1], /*dest*/ str_length - curr_column + 1); curr_column--; str_length--; } break; case DELETE_KEY: if (curr_column < str_length) { movmem( &buffer[curr_column+1], /*source*/ &buffer[curr_column], /*dest*/ str_length - curr_column); str_length--; } break; default: if (((c >= ' ') && (c <= '~')) && (str_length < max_length)) { if (insert_mode) { movmem( &buffer[curr_column], &buffer[curr_column + 1], str_length - curr_column + 1); str_length++; } else if (curr_column >= str_length) str_length++; buffer[curr_column] = c; curr_column++; } break; } buffer[str_length] = '\0'; } while ((c != ENTER_KEY) && (c != ESCAPE_KEY)); } [LISTING TWO] /**************************************************************************** Excerpts from BUF_GAP.C--buffer gap manager module. Derived by Ray Valdes from code by Joseph H. Allen, who wrote in his post to the comp.editors newsgroup on 9/10/89: "Do whatever you like with this, just leave my name on it." *****************************************************************************/ private unsigned sizeofBuffer; /* The size of theBuffer */ private char* thePoint; /* The point */ private char* theBuffer; /* The buffer */ private char* theEndOfBuffer; /* First character not in buffer */ private char* theStartOfGap; /* Beginning of theStartOfGap */ private char* theEndOfGap; /* First character not in theStartOfGap */ private bool isBufferChanged; /* Set when file has been changed */ #define SIZEOF_GAP_INCREMENT 16384 /* Amount that the buffgap grows by */ /****************************************************************/ public bool bg_InitializeModule(void) { sizeofBuffer = SIZEOF_GAP_INCREMENT; theBuffer = (char* ) mem_AllocMem(sizeofBuffer); if(!theBuffer) return FALSE; thePoint = theBuffer; theStartOfGap = theBuffer; theEndOfGap = theBuffer + SIZEOF_GAP_INCREMENT; theEndOfBuffer= theEndOfGap; return TRUE; } /****************************************************************/ public void bg_ExpandBuffer(unsigned amount) { if( (theEndOfBuffer + amount - theBuffer) > sizeofBuffer) { char* old = theBuffer; sizeofBuffer = theEndOfBuffer + amount + SIZEOF_GAP_INCREMENT - theBuffer; theBuffer = (char* ) mem_ReallocMem(theBuffer, sizeofBuffer); if(!theBuffer) ProgramError("ReallocMem failed!"); thePoint += theBuffer - old; theEndOfBuffer += theBuffer - old; theStartOfGap += theBuffer - old; theEndOfGap += theBuffer - old; } } /****************************************************************/ public void bg_MoveGapToPoint(void) { if(thePoint==theStartOfGap) return; if(thePoint==theEndOfGap) { thePoint = theStartOfGap; return; } /*else*/ if(thePoint < theStartOfGap) { bg_MoveBytes( theEndOfGap - (theStartOfGap-thePoint), thePoint, theStartOfGap - thePoint); theEndOfGap = theEndOfGap-(theStartOfGap-thePoint); theStartOfGap = thePoint; } else { bg_MoveBytes(theStartOfGap,theEndOfGap,thePoint-theEndOfGap); theStartOfGap += thePoint-theEndOfGap; theEndOfGap = thePoint; thePoint = theStartOfGap; } } /****************************************************************/ public void bg_ExpandGap(unsigned size) { if(size > bg_SizeofGap()) { size += SIZEOF_GAP_INCREMENT; bg_ExpandBuffer(size); bg_MoveBytes(theEndOfGap+size, theEndOfGap, theEndOfBuffer - theEndOfGap); theEndOfGap += size; theEndOfBuffer += size; } } /****************************************************************/ public bool bg_FindNextNewline(void) { while(((thePoint==theStartOfGap) ? (thePoint=theEndOfGap) : (thePoint)) != theEndOfBuffer) { if(*thePoint==NEWLINE_CH) return TRUE; else thePoint++; } return FALSE; } /****************************************************************/ public void bg_InsertStringAtPoint(char* string, unsigned size) { bg_MoveGapToPoint(); if(size > bg_SizeofGap()) bg_ExpandGap(size); bg_MoveBytes(theStartOfGap,string,size); theStartOfGap += size; isBufferChanged = TRUE; } /****************************************************************/ public bool bg_CompareString(char* string, unsigned size) { char* x; if(thePoint==theStartOfGap) thePoint=theEndOfGap; if( (theStartOfGap > thePoint ) && (theStartOfGap < thePoint + size ) && (theStartOfGap != theEndOfGap) ) { if(bg_CompareString(string,theStartOfGap-thePoint)) return TRUE; else { x = thePoint; thePoint = theEndOfGap; if(bg_CompareString( string + (theStartOfGap-x) , size - (theStartOfGap-x))) { thePoint=x; return TRUE; } else { thePoint=x; return FALSE; } } } else { x = thePoint; do { if(*(x++) != *(string++)) return TRUE; } while(--size); return FALSE; } } /****************************************************************/ public bool /*this routine assumes file is already open*/ bg_InsertFile(FILE* file) { unsigned amount; long file_size = filelength(fileno(file)); if(file_size==0L) return TRUE; if(file_size > 32767L) return FALSE; isBufferChanged = TRUE; bg_MoveGapToPoint(); bg_ExpandGap((int)file_size); amount = fread(theStartOfGap, 1, file_size, file); if(amount != file_size) { ProgramError("I/O Error on reading file."); return FALSE; } theStartOfGap += amount; return TRUE; }