/* The cut-paste module for splitvt */ #include #include #include #include "vt100.h" #include "video.h" #include "splitvt.h" #include "terminal.h" #define RIGHT 0x01 #define LEFT 0x02 #define Min(A,B) ((A>B)?B:A) #define Max(A,B) ((A>B)?A:B) /* Variables used by the cut-paste motion functions */ static int marked, oldattr; static unsigned char on; extern struct physical physical; static int lastdirection=0; /* This function assumes that it alone will print selected text */ static void put_sel_char(win, x, y, oldattr, on, direction) window *win; int x, y; int *oldattr; unsigned char *on; int direction; { int c, selected=0; c = get_video(win, x, y); /* Toggle selection highlighting */ if ( direction ) { /*fprintf(stderr, "Turning %s...\n", direction == RIGHT ? "right" : "left");*/ if ( lastdirection && lastdirection != direction ) /* We turned... */ ; else { c ^= (SELECTED<<8); selected = ( ((c>>8)&SELECTED) ? 1 : 0 ); } lastdirection=direction; } else c ^= (SELECTED<<8); (*oldattr)=check_attr(c, *oldattr, (int)on); put_video(c, win, x, y); if ( c&0xFF ) printf("%c", c&0xFF); else printf(" "); if ( direction ) { if ( !selected ) { if ( direction == RIGHT ) { if ( y < win->cols ) ++y; else goto end; } else { if ( y > 1 ) --y; else goto end; vt_left(2); } c = get_video(win, x, y); if ( c&0xFF ) printf("%c", c&0xFF); else printf(" "); vt_left(1); } else if ( direction == LEFT ) vt_left(2); } end: fflush(stdout); return; } /* If this function returns 0, no selection was made */ static char *extract_sel(win, buf, len, mark1, mark2) window *win; char *buf; int len; position *mark1, *mark2; { position startsel, endsel; if ( mark1->x == mark2->x ) { if ( mark1->y == mark2->y ) { vt_info("Selection cancelled."); clrsel_video(win); reset_bar(1); return(NULL); } if ( mark1->y < mark2->y ) { startsel = (*mark1); endsel = (*mark2); ++endsel.y; } else { startsel = (*mark2); endsel = (*mark1); ++endsel.y; } } else if ( mark1->x < mark2->x ) { startsel = (*mark1); endsel = (*mark2); } else if ( mark1->x > mark2->x ) { startsel = (*mark2); endsel = (*mark1); } getsel_video(win,buf,len, startsel.x, endsel.x, startsel.y, endsel.y); clrsel_video(win); vt_info("Region selected."); reset_bar(1); return(buf); } static void line_down(win, cursor) window *win; position *cursor; { int j; if ( cursor->x < win->rows ) { if ( marked ) { for (j=cursor->y; jcols; ++j) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } printf("\r"); vt_down(1); ++cursor->x; for ( j=1; jy; ++j ) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } } else { vt_down(1); ++cursor->x; } } } static void line_up(win, cursor) window *win; position *cursor; { int j; if ( cursor->x > 1 ) { --cursor->x; if ( marked ) { vt_up(1); for (j=cursor->y; jcols; ++j) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } printf("\r"); vt_down(1); ++cursor->x; for ( j=1; jy; ++j ) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } vt_up(1); --cursor->x; } else vt_up(1); } } static void move_left(win, cursor) window *win; position *cursor; { if ( cursor->y > 1 ) { if ( marked ) { put_sel_char(win, cursor->x, cursor->y, &oldattr, &on, LEFT); } else vt_left(1); --cursor->y; } } static void move_right(win, cursor) window *win; position *cursor; { if ( cursor->y < win->cols ) { if ( marked ) put_sel_char(win, cursor->x, cursor->y, &oldattr, &on, RIGHT); else vt_right(1); ++cursor->y; } } static int use_xcb=0; /* Do we use xcb to access X selection buffers? */ void vt_initsel() { extern char *pathsearch(); /* From misc.c */ #ifdef USE_XCB char *display; /* Use xcb if we have both an X display and the command. */ /* xcb needs to support my hacked '-R' option. */ if ( (display=(char *)getenv("DISPLAY")) && pathsearch("xcb", 1) ) use_xcb=1; else #endif use_xcb=0; } static char selbuf[BUFSIZ]; char *vt_getselbuf() { FILE *safe_popen(); /* From misc.c */ FILE *xcb; char buffer[BUFSIZ]; int len; if ( use_xcb ) { if ( (xcb=safe_popen("xcb -S 0 && xcb -p 0", "r")) == NULL ) return(selbuf); len=fread(buffer, sizeof(char), BUFSIZ-1, xcb); (void) safe_pclose(xcb); if ( len > 0 ) { buffer[len]='\0'; strcpy(selbuf, buffer); } } return(selbuf); } char *vt_setselbuf(buffer) char *buffer; { FILE *safe_popen(); /* From misc.c */ FILE *xcb; strncpy(selbuf, buffer, BUFSIZ-1); selbuf[BUFSIZ-1]='\0'; if (use_xcb && (xcb=safe_popen("xcb -s 0; xcb -RT 0", "w")) != NULL) { (void) fwrite(selbuf, sizeof(char), strlen(selbuf), xcb); (void) safe_pclose(xcb); } return(selbuf); } /* Get a window selection */ char *vt_getsel(win, buf, len) int win; char *buf; int len; { int c; position here, cursor, mark1, mark2; window *thiswin; thiswin = physical.subwins[win]; here=cursor=thiswin->cursor; marked=lastdirection=0; vt_info("Mark beginning of selection: "); while ( (c=getchar()) != EOF ) { switch (c) { case 'j': /* Move down one line */ line_down(thiswin, &cursor); break; case 'k': /* Move up one line */ line_up(thiswin, &cursor); break; case 'l': /* Move right one char */ move_right(thiswin, &cursor); break; case 'h': /* Move left one char */ move_left(thiswin, &cursor); break; case ' ': /* Mark selection */ if ( marked ) { mark2=cursor; /* Copy and deselect area */ buf=extract_sel(thiswin, buf, len, &mark1, &mark2); /* Repaint the screen */ paint_video(thiswin); return(buf); } else { mark1=cursor; oldattr = get_video(thiswin, mark1.x, mark1.y); on = (oldattr>>8); marked=1; vt_info( "Mark end of selection: "); /* Set reverse here */ vt_update(); } break; case '\033': case 'q': /* Cancel selection */ clrsel_video(thiswin); vt_goto((here.x+thiswin->row_offset), here.y); vt_info("Selection cancelled."); sleep(1); /* Repaint the screen */ paint_video(thiswin); return(NULL); break; default: break; } } return NULL; /* Hopefully, we never reach here */ } /* Set a window selection */ char *vt_setsel(buf, len, startx, endx, starty, endy) char *buf; int len; int startx, starty; int endx, endy; { window *thiswin; /* If nothing selected, return old selection */ if ( (startx == endx) && (starty == endy) ) return(buf); if ( startx == (physical.subwins[LOWER])->row_offset ) { /* Separator bar; return */ return(buf); } else if ( startx < (physical.subwins[LOWER])->row_offset ) { thiswin = physical.subwins[UPPER]; } else { thiswin = physical.subwins[LOWER]; startx-=thiswin->row_offset; endx-=thiswin->row_offset; } getsel_video(thiswin, buf, len, startx, endx, starty, endy); return(buf); }