1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <memdraw.h> 5 #include <thread.h> 6 #include <cursor.h> 7 #include <mouse.h> 8 #include <keyboard.h> 9 #include <frame.h> 10 #include <plumb.h> 11 #include <html.h> 12 #include "dat.h" 13 #include "fns.h" 14 15 void 16 rowinit(Row *row, Rectangle r) 17 { 18 Rectangle r1; 19 Text *t; 20 21 draw(screen, r, display->white, nil, ZP); 22 row->r = r; 23 row->col = nil; 24 row->ncol = 0; 25 r1 = r; 26 r1.max.y = r1.min.y + font->height; 27 t = &row->tag; 28 textinit(t, screen, r1, font, tagcols); 29 t->what = Rowtag; 30 t->row = row; 31 t->w = nil; 32 t->col = nil; 33 r1.min.y = r1.max.y; 34 r1.max.y += Border; 35 draw(screen, r1, display->black, nil, ZP); 36 textinsert(t, 0, L"Newcol Google Exit ", 19); 37 textsetselect(t, t->rs.nr, t->rs.nr); 38 } 39 40 Column* 41 rowadd(Row *row, Column *c, int x) 42 { 43 Rectangle r, r1; 44 Column *d; 45 int i; 46 47 d = nil; 48 r = row->r; 49 r.min.y = row->tag.r.max.y+Border; 50 if(x<r.min.x && row->ncol>0){ /*steal 40% of last column by default */ 51 d = row->col[row->ncol-1]; 52 x = d->r.min.x + 3*Dx(d->r)/5; 53 } 54 /* look for column we'll land on */ 55 for(i=0; i<row->ncol; i++){ 56 d = row->col[i]; 57 if(x < d->r.max.x) 58 break; 59 } 60 if(row->ncol > 0){ 61 if(i < row->ncol) 62 i++; /* new column will go after d */ 63 r = d->r; 64 if(Dx(r) < 100) 65 return nil; 66 draw(screen, r, display->white, nil, ZP); 67 r1 = r; 68 r1.max.x = min(x, r.max.x-50); 69 if(Dx(r1) < 50) 70 r1.max.x = r1.min.x+50; 71 colresize(d, r1); 72 r1.min.x = r1.max.x; 73 r1.max.x = r1.min.x+Border; 74 draw(screen, r1, display->black, nil, ZP); 75 r.min.x = r1.max.x; 76 } 77 if(c == nil){ 78 c = emalloc(sizeof(Column)); 79 colinit(c, r); 80 }else 81 colresize(c, r); 82 c->row = row; 83 c->tag.row = row; 84 row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*)); 85 memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*)); 86 row->col[i] = c; 87 row->ncol++; 88 clearmouse(); 89 return c; 90 } 91 92 void 93 rowresize(Row *row, Rectangle r) 94 { 95 int i, dx, odx; 96 Rectangle r1, r2; 97 Column *c; 98 99 dx = Dx(r); 100 odx = Dx(row->r); 101 row->r = r; 102 r1 = r; 103 r1.max.y = r1.min.y + font->height; 104 textresize(&row->tag, screen, r1); 105 r1.min.y = r1.max.y; 106 r1.max.y += Border; 107 draw(screen, r1, display->black, nil, ZP); 108 r.min.y = r1.max.y; 109 r1 = r; 110 r1.max.x = r1.min.x; 111 for(i=0; i<row->ncol; i++){ 112 c = row->col[i]; 113 r1.min.x = r1.max.x; 114 if(i == row->ncol-1) 115 r1.max.x = r.max.x; 116 else 117 r1.max.x = r1.min.x+Dx(c->r)*dx/odx; 118 if(i > 0){ 119 r2 = r1; 120 r2.max.x = r2.min.x+Border; 121 draw(screen, r2, display->black, nil, ZP); 122 r1.min.x = r2.max.x; 123 } 124 colresize(c, r1); 125 } 126 } 127 128 void 129 rowdragcol(Row *row, Column *c, int) 130 { 131 Rectangle r; 132 int i, b, x; 133 Point p, op; 134 Column *d; 135 136 clearmouse(); 137 setcursor(mousectl, &boxcursor); 138 b = mouse->buttons; 139 op = mouse->xy; 140 while(mouse->buttons == b) 141 readmouse(mousectl); 142 setcursor(mousectl, nil); 143 if(mouse->buttons){ 144 while(mouse->buttons) 145 readmouse(mousectl); 146 return; 147 } 148 149 for(i=0; i<row->ncol; i++) 150 if(row->col[i] == c) 151 goto Found; 152 error("can't find column"); 153 154 Found: 155 if(i == 0) 156 return; 157 p = mouse->xy; 158 if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5)) 159 return; 160 if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){ 161 /* shuffle */ 162 x = c->r.min.x; 163 rowclose(row, c, FALSE); 164 if(rowadd(row, c, p.x) == nil) /* whoops! */ 165 if(rowadd(row, c, x) == nil) /* WHOOPS! */ 166 if(rowadd(row, c, -1)==nil){ /* shit! */ 167 rowclose(row, c, TRUE); 168 return; 169 } 170 colmousebut(c); 171 return; 172 } 173 d = row->col[i-1]; 174 if(p.x < d->r.min.x+80+Scrollsize) 175 p.x = d->r.min.x+80+Scrollsize; 176 if(p.x > c->r.max.x-80-Scrollsize) 177 p.x = c->r.max.x-80-Scrollsize; 178 r = d->r; 179 r.max.x = c->r.max.x; 180 draw(screen, r, display->white, nil, ZP); 181 r.max.x = p.x; 182 colresize(d, r); 183 r = c->r; 184 r.min.x = p.x; 185 r.max.x = r.min.x; 186 r.max.x += Border; 187 draw(screen, r, display->black, nil, ZP); 188 r.min.x = r.max.x; 189 r.max.x = c->r.max.x; 190 colresize(c, r); 191 colmousebut(c); 192 } 193 194 void 195 rowclose(Row *row, Column *c, int dofree) 196 { 197 Rectangle r; 198 int i; 199 200 for(i=0; i<row->ncol; i++) 201 if(row->col[i] == c) 202 goto Found; 203 error("can't find column"); 204 Found: 205 r = c->r; 206 if(dofree) 207 colcloseall(c); 208 memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*)); 209 row->ncol--; 210 row->col = realloc(row->col, row->ncol*sizeof(Column*)); 211 if(row->ncol == 0){ 212 draw(screen, r, display->white, nil, ZP); 213 return; 214 } 215 if(i == row->ncol){ /* extend last column right */ 216 c = row->col[i-1]; 217 r.min.x = c->r.min.x; 218 r.max.x = row->r.max.x; 219 }else{ /* extend next window left */ 220 c = row->col[i]; 221 r.max.x = c->r.max.x; 222 } 223 draw(screen, r, display->white, nil, ZP); 224 colresize(c, r); 225 } 226 227 Column* 228 rowwhichcol(Row *row, Point p) 229 { 230 int i; 231 Column *c; 232 233 for(i=0; i<row->ncol; i++){ 234 c = row->col[i]; 235 if(ptinrect(p, c->r)) 236 return c; 237 } 238 return nil; 239 } 240 241 Text* 242 rowwhich(Row *row, Point p, Rune r, int key) 243 { 244 Column *c; 245 246 if(ptinrect(p, row->tag.all)) 247 return &row->tag; 248 c = rowwhichcol(row, p); 249 if(c) 250 return colwhich(c, p, r, key); 251 return nil; 252 } 253