URI: 
       lineset.c - gramscii - A simple editor for ASCII box-and-arrow charts
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
       lineset.c (4125B)
       ---
            1 #define _POSIX_C_SOURCE 200112L
            2 
            3 #include <stdio.h>
            4 #include <stdlib.h>
            5 #include <string.h>
            6 #include "gramscii.h"
            7 
            8 /** extern declarations **/
            9 
           10 extern lineset_t screen; /* what is visualised */
           11 extern lineset_t cutbuf; /* cut/paste buffer */
           12 extern lineset_t *undo;  /* undo list */
           13 
           14 extern int undo_sz;/* allocated size of undo list*/
           15 extern int undo_cur;/* undo position */
           16 extern int undo_lst;/* last valid undo position */
           17 
           18 extern int WIDTH, HEIGHT;
           19 
           20 extern char modified; /* set to 1 if screen modified since last save */
           21 
           22 /****/
           23 
           24 static int LONG_STEP;
           25 
           26 /* line_t and lineset_t management */
           27 
           28 void ensure_line_length(line_t *l, int len){
           29         char *tmp;
           30 
           31         if (l->sz < len + 1){
           32                 tmp = realloc(l->s, (len+1) * 2 * sizeof(char));
           33                 if (tmp == NULL){
           34                         fprintf(stderr, "Unable to allocate string\n");
           35                         cleanup(1);
           36                 }
           37                 l->s = tmp;
           38                 l->sz = (len + 1) * 2;
           39         }
           40 }
           41 
           42 
           43 void alloc_line(line_t *l){
           44         char *tmp;
           45 
           46         l->sz = WIDTH+1;
           47         tmp = malloc((l->sz) * sizeof(char));
           48         if (tmp == NULL){
           49                 fprintf(stderr, "unable to allocate line\n");
           50                 cleanup(1);
           51         }
           52         l->s = tmp;
           53         memset(l->s, BG, l->sz);
           54         l->lst = -1;
           55         l->s[0]='\0';
           56 }
           57 
           58 void ensure_num_lines(lineset_t *ls, int n){
           59         line_t *tmp;
           60 
           61         if (n > ls->sz){
           62                 if (ls->sz == 0)
           63                         ls->l=NULL;
           64                 tmp = realloc(ls->l, (n + LONG_STEP) * sizeof(line_t));
           65                 if (tmp == NULL){
           66                         fprintf(stderr, "Unable to allocate memory for more lines");
           67                         cleanup(1);
           68                 }
           69                 else {
           70                         ls->l = tmp;
           71                         while ( ls->sz < n + LONG_STEP){
           72                                 alloc_line(&(ls->l[ls->sz]));
           73                                 ls->sz ++;
           74                         }
           75                 }
           76         }
           77 }
           78 
           79 
           80 void dump_lines(lineset_t ls, FILE *f){
           81         int i;
           82         for (i=0; i<ls.num ;i++){
           83                 fprintf(f, "%s\n", ls.l[i].s);
           84         }
           85         fflush(f);
           86 }
           87 
           88 void pad_line_to_length(char *s, int W){
           89 
           90         int i;
           91 
           92         for (i=strlen(s); i<W; i++){
           93                 s[i] = BG;
           94         }
           95 }
           96 
           97 /* cut/yank/paste/undo management */
           98 
           99 void yank_region(int x1, int y1, int x2, int y2){
          100 
          101         int N, W, i;
          102 
          103         N = y2 - y1 + 1;
          104         W = x2 - x1 + 1;
          105         ensure_num_lines(&cutbuf, N);
          106         
          107         for (i=y1; i<=y2; i++){
          108                 ensure_line_length(&(cutbuf.l[i-y1]), W);
          109                 memcpy(cutbuf.l[i-y1].s, screen.l[i].s + x1, x2-x1+1);
          110                 if (strlen(cutbuf.l[i-y1].s) < W)
          111                         pad_line_to_length(cutbuf.l[i-y1].s, W);
          112                 cutbuf.l[i-y1].s[W] = '\0';
          113                 cutbuf.l[i-y1].n = i;
          114         }
          115         cutbuf.num = N;
          116 #ifdef DEBUG
          117         dump_lines(cutbuf, stderr);
          118 #endif
          119         
          120 }
          121 
          122 
          123 void paste_region(int x1, int y1){
          124         int i, curlen, pastelen;
          125 
          126         i = y1;
          127         while( i < HEIGHT && i < y1 + cutbuf.num){
          128                 pastelen = strlen(cutbuf.l[i-y1].s);
          129                 curlen = strlen(screen.l[i].s); 
          130                 memcpy(screen.l[i].s + x1, cutbuf.l[i-y1].s, pastelen);
          131                 if (curlen <= x1)
          132                         /* double-check this line below */
          133                         pad_line_to_length(screen.l[i].s + curlen, x1 - curlen);
          134                 if (curlen <= x1 + pastelen)
          135                         screen.l[i].s[x1 + pastelen] = '\0';
          136                 
          137                 screen.l[i].lst = strlen(screen.l[i].s) - 1;
          138 #ifdef DEBUG 
          139                 fprintf(stderr, "%d.lst: %d\n", i, screen.l[i].lst);
          140 #endif
          141                 i += 1;
          142                 modified = 1;
          143         }
          144         redraw();
          145 }
          146 
          147 void copy_lines_to_ring(int y1, int y2, int which){
          148         int i, len, idx;
          149         lineset_t *tmp;        
          150 
          151         if (y1 > y2){
          152                 y1 ^= y2;
          153                 y2 ^= y1;
          154                 y1 ^= y2;
          155         }
          156         if (undo_cur > undo_lst)
          157                 undo_cur = undo_lst;
          158         if (which == PRV_STATE){ /* adding a new previous state */
          159                 undo_cur += 2;
          160                 idx = undo_cur;
          161         }
          162         else
          163                 idx = undo_cur + 1;
          164         if (idx >= undo_sz - 1){
          165                 tmp = realloc(undo, (undo_sz + 10) * sizeof(lineset_t));
          166                 if (tmp == NULL){
          167                         fprintf(stderr, "Error allocating undo buffer");
          168                         cleanup(1);
          169                 }
          170                 undo = tmp;
          171                 for (i=0; i<10; i++){
          172                         undo[undo_sz + i].sz = 0;
          173                         undo[undo_sz + i].l = NULL;
          174                         undo[undo_sz + i].num = 0;
          175                 }
          176                 undo_sz += 10;
          177         }
          178         ensure_num_lines(&(undo[idx]), y2 - y1 + 1);
          179         for(i=y1; i<=y2; i++){
          180                 len = strlen(screen.l[i].s);
          181                 ensure_line_length(&(undo[idx].l[i-y1]), len);
          182                 strcpy(undo[idx].l[i-y1].s, screen.l[i].s);
          183                 undo[idx].l[i-y1].n = i;
          184                 undo[idx].l[i-y1].lst = screen.l[i].lst;
          185         }
          186         undo[idx].num = y2 - y1 + 1;
          187         if (which == PRV_STATE)
          188                 undo_lst = undo_cur;
          189 #ifdef DEBUG
          190         fprintf(stderr, "undo_ring: y1: %d y2: %d idx: %d\n", y1, y2, idx);
          191         for(i=0; i<undo[idx].num; i++){
          192                 fprintf(stderr, "UU: %d| %s\n", undo[idx].l[i].n, undo[idx].l[i].s);
          193         }
          194 #endif        
          195 }
          196 
          197 void invalidate_undo(){
          198         if (undo_lst > undo_cur)
          199                 undo_lst = undo_cur;
          200 }