home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / Mgr / Sparcmgr / src.zoo / src / cut.c < prev    next >
C/C++ Source or Header  |  1989-03-17  |  11KB  |  393 lines

  1. /*                        Copyright (c) 1987 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*    $Header: cut.c,v 1.2 89/03/17 08:38:10 sau Exp $
  9.     $Source: /m1/mgr.new/src/RCS/cut.c,v $
  10. */
  11. static char    RCSid_[] = "$Source: /m1/mgr.new/src/RCS/cut.c,v $$Revision: 1.2 $";
  12.  
  13. /* cut and paste text */
  14.  
  15. #include <stdio.h> 
  16. #include "bitmap.h"
  17. #include "defs.h"
  18. #include "font.h"
  19. #include "window.h"
  20. #include "event.h"
  21.  
  22. /* stuff global buffer into input stream */
  23.  
  24. int 
  25. paste()
  26.    {
  27.    if (snarf) {
  28.       do_event(EVENT_PASTE,active,E_MAIN);
  29.       Write(ACTIVE(to_fd),snarf,strlen(snarf));
  30. #ifdef DEBUG
  31.       dprintf(y)(stderr,"%s: Pasting [%s]\n",ACTIVE(tty), snarf?snarf:"EMPTY");
  32. #endif
  33.       }
  34. #ifdef DEBUG
  35.    else {
  36.       dprintf(y)(stderr,"%s: Nothing to paste\n",ACTIVE(tty));
  37.       }
  38. #endif
  39.    }
  40.  
  41. /* cut text from a window, put in global buffer */
  42.  
  43.  
  44. #define MAXROWS        64        /* greatest char height */
  45. #define MAXCOLS        32        /* widest char (bits in u-long) */
  46.  
  47. BITMAP *glyph;                /* spot for glyph comparison */
  48. unsigned long data[MAXROWS];        /* bit data for glyph */
  49. BITMAP *check;                /* other spot for glyph comparison */
  50. unsigned long data2[MAXROWS];        /* bit data for other glyph */
  51.  
  52. static struct entry **table;        /* hash table */
  53.  
  54. /* sweep out and cut text */
  55.  
  56. int
  57. cut()
  58.    {
  59.    register int i,j;
  60.    register WINDOW *win = active;        /* window to cut text from */
  61.    int count;                    /* # of snarfed chars */
  62.    int errors = 0;                /* number of misses */
  63.    int cols=1, rows=0;                /* rows and cols swept */
  64.    int col,row;                    /* starting col and row */
  65.    int maxcol;                    /* # of cols in row */
  66.    int x,y;                    /* bit position in bitmap */
  67.    int hcode;                    /* hash code */
  68.    int button;                    /* button from move_mouse */
  69.    char c;                    /* matched char */
  70.    char *pntr;                    /* current char in line */
  71.    struct entry *entry;                /* current hash table entry */
  72.    char *line;                    /* buffer to receive text */
  73.    char get_match(),*malloc();
  74.    char *to_tabs(), *fixline();
  75.  
  76.    /* return immediately if window is not snarffable */
  77.  
  78.    if ((W(flags) & W_SNARFABLE) ==0)
  79.       return(0);
  80.  
  81.    /* initialize comparison registers */
  82.  
  83.    glyph = bit_alloc(32,FSIZE(high),data,1);
  84.    check = bit_alloc(32,FSIZE(high),data2,1);
  85.    bit_blit(check,0,0,32,FSIZE(high),BIT_CLR,NULL_DATA,0,0);
  86.  
  87.    /* build hash table */
  88.  
  89.    if ((table = W(font)->table) == NULL) {
  90. #ifdef DEBUG
  91.       dprintf(C)(stderr,"building cut table\n");
  92. #endif
  93.       table = W(font)->table =
  94.                     (struct entry **) malloc (sizeof (struct entry) * H_SIZE);
  95.       bzero(table, sizeof(struct entry) * H_SIZE);
  96.    
  97.       for(i = FSIZE(start);i<FSIZE(start)+FSIZE(count);i++) {
  98.          if (W(font)->glyph[i] && i >= ' ') {
  99.             hcode = get_hash(W(font)->glyph[i],0,0,FSIZE(wide),FSIZE(high),0);
  100.             enter(hcode,i);
  101.             }
  102.          }
  103.       }
  104.  
  105.    /* find cut region */
  106.  
  107.    SETMOUSEICON(&mouse_cut);
  108.    button = move_mouse(screen,mouse,&mousex,&mousey,0);
  109.    SETMOUSEICON(&mouse_arrow);
  110.    i = get_text(screen,mouse,mousex,mousey,&cols,&rows,win,E_SWTEXTT);
  111.    if (i == 0) {
  112.       do_button(0);
  113.       return(0);
  114.    }
  115.  
  116.    /* find extent of cut region */
  117.  
  118.    col = (mousex-(W(x0)+SUM_BDR+W(text.x)))/FSIZE(wide);
  119.    maxcol = (W(text.wide) ? W(text.wide) : BIT_WIDE(W(window)))/FSIZE(wide);
  120.    row = (mousey-(W(y0)+SUM_BDR+W(text.y)))/FSIZE(high);
  121.  
  122.    if (W(flags)&W_SNARFLINES) {        /* snarf lines only */
  123. #ifdef DEBUG
  124.       dprintf(C)(stderr,"Cutting lines only\n");
  125. #endif
  126.       col = 0;
  127.       cols = maxcol;
  128.       }
  129.  
  130. #ifdef DEBUG
  131.    dprintf(C)(stderr,"Cut got %d,%d  %d x %d\n",col,row,cols,rows);
  132. #endif
  133.  
  134.    /* look up characters */
  135.  
  136.    pntr = line = malloc(1+(1+maxcol)*(rows+1));    /* max possible cut */
  137.    switch(rows) {
  138.       case 0:            /* 1 row */
  139.          y = W(text.y)+row*FSIZE(high);
  140.          for(x=W(text.x)+col*FSIZE(wide),i=0;i<cols;i++,x+=FSIZE(wide)) {
  141.             c = get_match(W(window),x,y,FSIZE(wide),FSIZE(high));
  142.             *pntr++ = c ? c : (errors++,C_NOCHAR);
  143.             }
  144.          if (col+cols == maxcol && c==' ')
  145.             pntr = fixline(line,pntr);
  146.          break;
  147.       case 1:            /* 2 rows */
  148.          y = W(text.y)+row*FSIZE(high);
  149.          for(x=W(text.x)+col*FSIZE(wide),i=0;i<maxcol;i++,x+=FSIZE(wide)) {
  150.             c = get_match(W(window),x,y,FSIZE(wide),FSIZE(high));
  151.             *pntr++ = c ? c : (errors++,C_NOCHAR);
  152.             }
  153.          pntr = fixline(line,pntr);
  154.  
  155.          y += FSIZE(high);
  156.          for(x=W(text.x),i=0;i<col+cols;i++,x+=FSIZE(wide)) {
  157.             c = get_match(W(window),x,y,FSIZE(wide),FSIZE(high));
  158.             *pntr++ = c ? c : (errors++,C_NOCHAR);
  159.             }
  160.          if (col+cols == maxcol && c==' ')
  161.             pntr = fixline(line,pntr);
  162.          break;
  163.  
  164.       default:            /* > 2 rows */
  165.          y = W(text.y)+row*FSIZE(high);
  166.          for(x=W(text.x)+col*FSIZE(wide),i=0;i<maxcol;i++,x+=FSIZE(wide)) {
  167.             c = get_match(W(window),x,y,FSIZE(wide),FSIZE(high));
  168.             *pntr++ = c ? c : (errors++,C_NOCHAR);
  169.             }
  170.          pntr = fixline(line,pntr);
  171.  
  172.          for(j=0;j<rows-1;j++) {
  173.             y += FSIZE(high);
  174.             for(x=W(text.x),i=0;i<maxcol;i++,x+=FSIZE(wide)) {
  175.                c = get_match(W(window),x,y,FSIZE(wide),FSIZE(high));
  176.                *pntr++ = c ? c : (errors++,C_NOCHAR);
  177.                }
  178.             pntr = fixline(line,pntr);
  179.             }
  180.  
  181.          y += FSIZE(high);
  182.          for(x=W(text.x),i=0;i<col+cols;i++,x+=FSIZE(wide)) {
  183.             c = get_match(W(window),x,y,FSIZE(wide),FSIZE(high));
  184.             *pntr++ = c ? c : (errors++,C_NOCHAR);
  185.             }
  186.          if (col+cols == maxcol && c==' ')
  187.             pntr = fixline(line,pntr);
  188.  
  189.          break;
  190.       }
  191.    *pntr = '\0';
  192.    bit_destroy(check);
  193.    bit_destroy(glyph);
  194.  
  195.    /* put text into snarf buffer */
  196.  
  197.    count = pntr-line;
  198. #ifdef DEBUG
  199.    dprintf(C)(stderr,"snarfed %d chars, %d errors\n",count,errors);
  200.    dprintf(C)(stderr,"snarfed [%s]\n",line);
  201. #endif
  202.  
  203.    if (!(W(flags)&W_SNARFHARD)  && errors > 0 || 2*errors > count) {
  204.       oops();
  205.       count = 0;
  206.       }
  207.    else {
  208.       if (W(flags)&W_SNARFTABS)
  209.          to_tabs(col,line,line);
  210.  
  211.       if (snarf && button < BUTTON_SYS) {            /* add to cut buffer */
  212.          char *tmp = malloc(strlen(snarf) + strlen(line) +1);
  213.          count += strlen(snarf);
  214.          strcpy(tmp,snarf);
  215.          strcat(tmp,line);
  216.          free(snarf);
  217.          free(line);
  218.          snarf = tmp;
  219.          }
  220.       else if (snarf) {                    /* replace cut buffer */
  221.          free(snarf);
  222.          snarf = line;
  223.          }
  224.       else                        /* new cut buffer */
  225.          snarf = line;
  226.  
  227.       /* send snarf events (if any) */
  228.       id_message = W(pid);
  229.       for(win=active;win != (WINDOW *) 0;win=W(next))
  230.          do_event(EVENT_SNARFED,win,E_MAIN);
  231.       }
  232.    do_button(0);
  233.    return(count);
  234.    }
  235.  
  236. /* given bitmap, get hash code */
  237.  
  238. static int
  239. get_hash(map,x,y,w,h,how)
  240. BITMAP *map;
  241. int x,y,w,h;        /* where in map */  
  242. int how;        /* 0-> normal, 1->inverted */
  243.    {
  244.    register unsigned long sum = 0;
  245.    register int i,j;
  246.    bit_blit(glyph,0,0,32,h,BIT_CLR,NULL_DATA,0,0);
  247.    bit_blit(glyph,32-w,0,w,h,how ? BIT_NOT(BIT_SRC) : BIT_SRC,map,x,y);
  248.          for (j=0;j<h;j++)
  249.             sum += data[j]*(j+1);
  250.    return(sum%H_SIZE);
  251.    }
  252.  
  253. /* enter a glyph into the hash table */
  254.  
  255. static int
  256. enter(item,value)
  257. int item;
  258. unsigned char value;
  259.    {
  260.    register struct entry *entry;
  261.    char *malloc();
  262.  
  263.    if (table[item] == (struct entry *) 0) {
  264.       table[item] = (struct entry *) malloc(sizeof (struct entry));
  265.       table[item] -> value = value;
  266.       table[item] -> next = (struct entry *) 0;
  267.       }
  268.    else {
  269.       for(entry = table[item];entry->next;entry = entry -> next);
  270.       entry -> next  = (struct entry *) malloc(sizeof (struct entry));
  271.       entry -> next -> value = value;
  272.       entry -> next -> next = (struct entry *) 0;
  273.       }
  274.    }
  275.  
  276. /* find a character match in current font */
  277.  
  278. static char
  279. get_match(map,x,y,w,h)
  280. BITMAP *map;                /* bitmap containing text */
  281. int x,y,w,h;                /* position of glyph in "map" */
  282.    {
  283.    register struct entry *entry;
  284.    register WINDOW *win = active;
  285.    int code;                /* hash code */
  286.    int size = sizeof(long) * h;
  287.  
  288.    code = get_hash(map,x,y,w,h,0);        /* leaves char in glyph */
  289.    for(entry=table[code];entry;entry=entry->next) {
  290.       bit_blit(check,32-w,0,w,h,BIT_SRC,W(font)->glyph[entry->value],0,0);
  291.       if (bcmp(data,data2,size)==0) {
  292.          return(entry->value);
  293.          }
  294.       }
  295.  
  296.    /* try inverse video version */
  297.  
  298.    code = get_hash(map,x,y,w,h,1);        /* leaves char in glyph */
  299.    for(entry=table[code];entry;entry=entry->next) {
  300.       bit_blit(check,32-w,0,w,h,BIT_SRC,W(font)->glyph[entry->value],0,0);
  301.       if (bcmp(data,data2,size)==0) {
  302.          return(entry->value);
  303.          }
  304.       }
  305.    return('\0');
  306.    }
  307.    
  308. /* zap a font hash table */
  309.  
  310. zap_fhash(fnt)
  311. struct font *fnt;
  312.    {
  313.    register struct entry *entry, *next;
  314.    register int i;
  315.  
  316.    if (fnt->table) {
  317.       for(i=0;i<H_SIZE;i++)
  318.          for(entry=table[i];entry;entry=next) {
  319.             next = entry->next;
  320.             free(entry);
  321.             }
  322.       free(fnt->table);
  323.       }
  324.    }
  325.  
  326. /* change trailing white space into \n */
  327.  
  328. char *
  329. fixline(s,pnt)
  330. char *s;
  331. register char *pnt;
  332.    {
  333.    while (*--pnt == ' ' && pnt > s);
  334.    *++pnt = '\n';
  335.    return(++pnt);
  336.    }
  337.  
  338. /* change spaces to tabs */
  339.  
  340. static char *
  341. to_tabs(pos,in,out)
  342. register int pos;                /* starting col # */
  343. register char *in;                /* input str */
  344. register char *out;                /* output str - tabs */
  345.    {
  346.    char *s = out;                /* start of out str */
  347.    register char c;                /* current input char */
  348.    register int spaces = 0;            /* # pending spaces */
  349.    
  350. #ifdef DEBUG
  351.    dprintf(C)(stderr,"-> TABS");
  352. #endif
  353.    while(pos++,c = *in++) {
  354.  
  355.       if (c=='\n' || c=='\r' || c=='\f')    /* reset column counter */
  356.          pos =0;
  357.  
  358.       if (c == ' ') {
  359.          spaces++;
  360.          if (pos && pos%8 == 0) {        /* ' ' -> \t */
  361.             c = '\t';
  362. #ifdef DEBUG
  363.             dprintf(C)(stderr,".");
  364. #endif
  365.             spaces=0;
  366.             }
  367.          }
  368.       else for(;spaces>0;spaces--) {        /* output spaces */
  369.          *out++ = ' ';
  370.          }
  371.          
  372.       if (spaces == 0)
  373.          *out++ = c;
  374.       }
  375.    *out = '\0';
  376. #ifdef DEBUG
  377.    dprintf(C)(stderr,"\n");
  378. #endif
  379.    return(s);
  380.    }
  381.  
  382. /* can't cut, ring bell */
  383.  
  384. static int
  385. oops()
  386.    {
  387.    register WINDOW *win = active;
  388.  
  389.    CLEAR(W(window),BIT_NOT(BIT_DST));
  390.    write(2,"\007",1);
  391.    CLEAR(W(window),BIT_NOT(BIT_DST));
  392.    }
  393.