/***************************************************************************** * * * command copy_mark() * * command copy_entire_line() * * command copy_entire_word() * * command kill_entire_line() * * command kill_entire_word() * * command kill_mark() * * command overlay_block() * * command set_mark_block() * * command set_mark_lines() * * command set_mark_region() * * command yank_mark() * * command yank_pop_mark() * * * * * *****************************************************************************/ #include #define SEARCH_FORWARD 1 #define SEARCH_BACKWARD -1 #define MARK_TYPE_REGION 0 #define MARK_TYPE_LINES 1 #define MARK_TYPE_BLOCK 2 #define MARK_TYPE_WORD 3 #define COPY_BLOCK 'c' #define KILL_BLOCK 'k' #define DELETE_BLOCK 'd' buffer short mark_type; buffer short kill_buff_type; buffer short kill_buff_width; int OldPoint = -1; int OldMark = -1; when_loading() { mark_type.default = MARK_TYPE_REGION; kill_buff_type.default = MARK_TYPE_REGION; kill_buff_width.default = 0; } /***************************************************************************** * copy-mark * *****************************************************************************/ command copy_mark() { switch (mark_type) { case MARK_TYPE_BLOCK: process_block(COPY_BLOCK); break; case MARK_TYPE_LINES: copy_marked_lines(); break; case MARK_TYPE_REGION: copy_region(); say("Region copied to %s", cur_kill_buf); break; case MARK_TYPE_WORD: copy_entire_word(); break; default: say("Invalid mark type. No action taken"); maybe_ding(); break; } } /***************************************************************************** * kill-mark * *****************************************************************************/ command kill_mark() { switch (mark_type) { case MARK_TYPE_BLOCK: process_block(KILL_BLOCK); break; case MARK_TYPE_LINES: kill_marked_lines(); break; case MARK_TYPE_REGION: kill_region(); say("Region killed to %s", cur_kill_buf); break; case MARK_TYPE_WORD: kill_entire_word(); break; default: say("Invalid mark type. No action taken"); maybe_ding(); break; } } /***************************************************************************** * yank-mark * *****************************************************************************/ command yank_mark() { int SaveCol; char *ThisBuff = bufname; short BufferType; /*---------------------------------------------------------------------------* * get current kill buffer type to determine which yank routine to call * *---------------------------------------------------------------------------*/ bufname = cur_kill_buf; if (bufname == ThisBuff) return; BufferType = kill_buff_type; bufname = ThisBuff; switch (BufferType) { case MARK_TYPE_LINES: SaveCol = current_column(); to_begin_line(); yank(); move_to_column(SaveCol); say("Lines yanked from %s", cur_kill_buf); break; case MARK_TYPE_REGION: yank(); say("Region yanked from %s", cur_kill_buf); break; case MARK_TYPE_BLOCK: yank_block(); break; case MARK_TYPE_WORD: yank(); say("Word yanked from %s", cur_kill_buf); break; default: say("Invalid kill-buffer type. No action taken"); break; } OldPoint = point; OldMark = mark; } /***************************************************************************** * yank pop mark * *****************************************************************************/ command yank_pop_mark() { int SaveCol; char *ThisBuff = bufname; short BufferType; /*---------------------------------------------------------------------------* * if point or mark have changed can't perform yank-pop * *---------------------------------------------------------------------------*/ if (OldPoint != point || OldMark != mark) { say(" "); return; } /*---------------------------------------------------------------------------* * get current kill buffer type to determine which yank routine to call * *---------------------------------------------------------------------------*/ bufname = cur_kill_buf; BufferType = kill_buff_type; bufname = ThisBuff; switch (BufferType) { case MARK_TYPE_LINES: SaveCol = current_column(); to_begin_line(); delete(mark, point); move_to_column(SaveCol); pop_kill(); yank_mark(); break; case MARK_TYPE_REGION: case MARK_TYPE_WORD: delete(mark, point); pop_kill(); yank_mark(); break; case MARK_TYPE_BLOCK: process_block(DELETE_BLOCK); pop_kill(); yank_mark(); break; default: say("Invalid kill-buffer type. No action taken"); break; } } /***************************************************************************** * copy current line to kill buffer * *****************************************************************************/ command copy_entire_line() { int i; int SavePoint = point; char *ThisBuff = bufname; /*---------------------------------------------------------------------------* * copy entire line into kill buffer * *---------------------------------------------------------------------------*/ to_begin_line(); i = point; if (!nl_forward()) insert('\n'); do_save_only(i, point); point = SavePoint; /*---------------------------------------------------------------------------* * set kill buffer type * *---------------------------------------------------------------------------*/ bufname = cur_kill_buf; kill_buff_type = MARK_TYPE_LINES; bufname = ThisBuff; say("Current line copied to %s", cur_kill_buf); } /***************************************************************************** * copy marked lines * *****************************************************************************/ copy_marked_lines() { int SavePoint = point; int SaveMark = mark; int TempPoint; int LineCount = 0; char *ThisBuff = bufname; /*---------------------------------------------------------------------------* * if point is less than mark exchange point and mark * *---------------------------------------------------------------------------*/ if (point < mark) { TempPoint = point; point = mark; mark = TempPoint; } /*---------------------------------------------------------------------------* * get pointer to beginning of first line and end of last line * *---------------------------------------------------------------------------*/ to_begin_line(); TempPoint = point; point = mark; to_begin_line(); mark = point; /*---------------------------------------------------------------------------* * count number of lines for "say" comment * *---------------------------------------------------------------------------*/ iter = 1; while (point < TempPoint) { nl_forward(); LineCount++; } /*---------------------------------------------------------------------------* * if point and mark were on same line * * call copy-entire-line * * return * * endif * *---------------------------------------------------------------------------*/ if (LineCount == 0) { copy_entire_line(); point = SavePoint; return; } /*---------------------------------------------------------------------------* * copy marked lines to kill buffer * * set kill buffer type * *---------------------------------------------------------------------------*/ do_save_only(mark, point); point = SavePoint; mark = SaveMark; bufname = cur_kill_buf; kill_buff_type = MARK_TYPE_LINES; bufname = ThisBuff; say("%d Lines copied to %s", LineCount, cur_kill_buf); } /***************************************************************************** * copy current word to kill buffer * *****************************************************************************/ command copy_entire_word() { int SavePoint = point; int SaveMark = mark; char *ThisBuff = bufname; iter = 1; forward_word(); mark = point; iter = 1; backward_word(); copy_region(); mark = SaveMark; point = SavePoint; bufname = cur_kill_buf; kill_buff_type = MARK_TYPE_WORD; bufname = ThisBuff; say("Word copied to %s", cur_kill_buf); } /***************************************************************************** * kill current word to kill buffer * *****************************************************************************/ command kill_entire_word() { int SavePoint = point; char *ThisBuff = bufname; iter = 1; forward_word(); mark = point; iter = 1; backward_word(); kill_region(); bufname = cur_kill_buf; kill_buff_type = MARK_TYPE_WORD; bufname = ThisBuff; say("Word killed to %s", cur_kill_buf); } /***************************************************************************** * kill entire line no matter where cursor is * *****************************************************************************/ command kill_entire_line() { int i; char *ThisBuff = bufname; to_begin_line(); i = point; nl_forward(); do_save_kill(i, point); bufname = cur_kill_buf; kill_buff_type = MARK_TYPE_LINES; bufname = ThisBuff; say("Current line killed to %s", cur_kill_buf); } /***************************************************************************** * kill a group of marked lines * *****************************************************************************/ kill_marked_lines() { int SavePoint = point; int TempPoint; int LineCount = 0; char *ThisBuff = bufname; /*---------------------------------------------------------------------------* * if point is less than mark exchange point and mark * *---------------------------------------------------------------------------*/ if (point < mark) { TempPoint = point; point = mark; mark = TempPoint; } /*---------------------------------------------------------------------------* * get pointer to beginning of first line and end of last line * *---------------------------------------------------------------------------*/ to_begin_line(); TempPoint = point; point = mark; to_begin_line(); mark = point; /*---------------------------------------------------------------------------* * count number of lines for "say" comment * *---------------------------------------------------------------------------*/ while (point < TempPoint) { nl_forward(); LineCount++; } /*---------------------------------------------------------------------------* * if point and mark were on same line * * call kill-entire-line * * return * * endif * *---------------------------------------------------------------------------*/ if (LineCount == 0) { kill_entire_line(); return; } /*---------------------------------------------------------------------------* * copy marked lines to kill buffer * * set kill buffer type * *---------------------------------------------------------------------------*/ point = SavePoint; do_save_kill(mark, TempPoint); bufname = cur_kill_buf; kill_buff_type = MARK_TYPE_LINES; bufname = ThisBuff; say("%d Lines killed to %s", LineCount, cur_kill_buf); } /***************************************************************************** * set the mark and the mark-type * *****************************************************************************/ command set_mark_block() { mark = point; mark_type = MARK_TYPE_BLOCK; say("Block mark set."); } command set_mark_lines() { mark = point; mark_type = MARK_TYPE_LINES; say("Lines mark set."); } command set_mark_region() { mark = point; mark_type = MARK_TYPE_REGION; say("Region mark set."); } /***************************************************************************** * copy, kill, or delete marked block * *****************************************************************************/ process_block(OpCode) char OpCode; { int i, j; short BlockWidth; int StartCol; int EndCol; int SavePoint; int SaveMark; char *ThisBuff = bufname; /*---------------------------------------------------------------------------* * do setup * *---------------------------------------------------------------------------*/ block_setup(&StartCol, &EndCol, &BlockWidth); SavePoint = point; SaveMark = mark; move_to_column(StartCol); if (OpCode != COPY_BLOCK) SavePoint = point; if (OpCode != DELETE_BLOCK) push_kill(); /*---------------------------------------------------------------------------* * transfer bytes from current buffer to current kill buffer * *---------------------------------------------------------------------------*/ while (point <= mark) { i = point; move_to_column(EndCol); j = point - i; if (OpCode != DELETE_BLOCK) xfer(cur_kill_buf, i, point); if (OpCode != COPY_BLOCK) delete(i, point); if (OpCode != DELETE_BLOCK) { bufname = cur_kill_buf; i = point; point = size(); if (character(point) == '\n') replace(point, ' '); if (j != BlockWidth) { while (j++ < BlockWidth) insert(' '); point = size(); } bufname = ThisBuff; } nl_forward(); move_to_column(StartCol); } if (OpCode != DELETE_BLOCK) { bufname = cur_kill_buf; modified = 0; kill_buff_type = MARK_TYPE_BLOCK; kill_buff_width = BlockWidth; bufname = ThisBuff; } /*---------------------------------------------------------------------------* * restore point and mark * *---------------------------------------------------------------------------*/ if (OpCode == COPY_BLOCK) { point = SavePoint; mark = SaveMark; say("Block copied to %s", cur_kill_buf); } else { point = SavePoint; mark = SavePoint; if (OpCode == KILL_BLOCK) say("Block killed to %s", cur_kill_buf); } } /***************************************************************************** * yank block buffer to current buffer * *****************************************************************************/ yank_block() { int BlockWidth; int StartCol; int SavePoint = point; int i; char *ThisBuff = bufname; /*---------------------------------------------------------------------------* * set mark to insert point * * get block width * *---------------------------------------------------------------------------*/ mark = point; StartCol = current_column(); bufname = cur_kill_buf; point = 0; BlockWidth = kill_buff_width; /*---------------------------------------------------------------------------* * transfer characters from current kill buffer to current buffer * *---------------------------------------------------------------------------*/ while (point < size()) { i = point; point += BlockWidth; xfer(ThisBuff, i, point); /*---------------------------------------------------------------------------* * increment insert point to next line in current buffer * * add a new line to end of buffer if necessary * *---------------------------------------------------------------------------*/ bufname = ThisBuff; if (!nl_forward()) insert('\n'); move_to_column(StartCol); if (current_column() < StartCol) to_column(StartCol); bufname = cur_kill_buf; } bufname = ThisBuff; nl_reverse(); move_to_column(StartCol + BlockWidth); mark = point; point = SavePoint; say("Block yanked from %s", cur_kill_buf); } /***************************************************************************** * overlay block to current buffer * *****************************************************************************/ command overlay_block() { int BlockWidth; int StartCol; int SavePoint = point; int i; char *ThisBuff = bufname; /*---------------------------------------------------------------------------* * set mark to insert point * * get block width * *---------------------------------------------------------------------------*/ mark = point; StartCol = current_column(); bufname = cur_kill_buf; if (kill_buff_type != MARK_TYPE_BLOCK) { say("Current kill-buffer is not a block"); bufname = ThisBuff; return; } point = 0; BlockWidth = kill_buff_width; /*---------------------------------------------------------------------------* * transfer characters from current kill buffer to current buffer * *---------------------------------------------------------------------------*/ while (point < size()) { i = point; point += BlockWidth; xfer(ThisBuff, i, point); /*---------------------------------------------------------------------------* * increment insert point to next line in current buffer * * add a new line to end of buffer if necessary * *---------------------------------------------------------------------------*/ bufname = ThisBuff; i = point; if (nl_forward()) point--; if (point > (i + BlockWidth)) point = i + BlockWidth; delete(i, point); if (!nl_forward()) insert('\n'); move_to_column(StartCol); if (current_column() < StartCol) to_column(StartCol); bufname = cur_kill_buf; } bufname = ThisBuff; nl_reverse(); move_to_column(StartCol + BlockWidth); mark = SavePoint; point = SavePoint; say("Block overlayed from %s", cur_kill_buf); } /***************************************************************************** * setup for block operations * *****************************************************************************/ block_setup(StartCol, EndCol, BlockWidth) int *StartCol; int *EndCol; int *BlockWidth; { int i, j, k; /*---------------------------------------------------------------------------* * get column number of opposite corners * * swap mark and point if necessary to put point on one of upper corners * *---------------------------------------------------------------------------*/ if (point > mark) { j = current_column(); /* one of the lower corners */ k = point; point = mark; i = current_column(); /* one of the upper corners */ mark = k; } else { i = current_column(); /* one of the upper corners */ k = point; point = mark; j = current_column(); /* one of the lower corners */ point = k; } /*---------------------------------------------------------------------------* * compute block width * *---------------------------------------------------------------------------*/ if (j > i) { *StartCol = i; *EndCol = j; *BlockWidth = j - i; } else { *StartCol = j; *EndCol = i; *BlockWidth = i - j; } }