From fd72e72dba33ed317125b87f9dec51175c490222 Mon Sep 17 00:00:00 2001 From: Stefan Frederik Date: Sun, 25 Sep 2022 21:11:52 +0200 Subject: [PATCH] test and got svg_embedded_graph(...) to work on Windows with Cairo (Joanne). added some #ifndef __unix__ guards to avoid compiler warnings about defined and not used functions, initial implementation of "Recent components" browser. --- src/actions.c | 22 ++++--- src/callback.c | 13 ++-- src/draw.c | 167 ++++++++++++++++++++++++++++++++++------------- src/hilight.c | 6 +- src/scheduler.c | 136 +++++++++++++++++++------------------- src/xschem.h | 5 +- src/xschem.tcl | 169 ++++++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 381 insertions(+), 137 deletions(-) diff --git a/src/actions.c b/src/actions.c index f3139736..35c57120 100644 --- a/src/actions.c +++ b/src/actions.c @@ -1010,6 +1010,8 @@ int place_symbol(int pos, const char *symbol_name, double x, double y, short rot if(i!=-1) { + tclvareval("c_toolbar add {", name, "}", NULL); + tclvareval("c_toolbar update; write_recent_file", NULL); check_inst_storage(); if(pos==-1 || pos > xctx->instances) n=xctx->instances; else @@ -1862,7 +1864,7 @@ void new_wire(int what, double mx_snap, double my_snap) ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1); storeobject(-1, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1,WIRE,0,0,NULL); hash_wire(XINSERT, xctx->wires-1, 1); - drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1, 0); + drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1, 0, NULL); } if(xctx->nl_yy2!=xctx->nl_yy1) { xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1; @@ -1870,7 +1872,7 @@ void new_wire(int what, double mx_snap, double my_snap) ORDER(xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2); storeobject(-1, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2,WIRE,0,0,NULL); hash_wire(XINSERT, xctx->wires-1, 1); - drawline(WIRELAYER,NOW, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0); + drawline(WIRELAYER,NOW, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0, NULL); } } else if(xctx->manhattan_lines==2) { if(xctx->nl_yy2!=xctx->nl_yy1) { @@ -1879,7 +1881,7 @@ void new_wire(int what, double mx_snap, double my_snap) ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2); storeobject(-1, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2,WIRE,0,0,NULL); hash_wire(XINSERT, xctx->wires-1, 1); - drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2, 0); + drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2, 0, NULL); } if(xctx->nl_xx2!=xctx->nl_xx1) { xctx->nl_xx1=xctx->nl_x1;xctx->nl_yy1=xctx->nl_y1; @@ -1887,7 +1889,7 @@ void new_wire(int what, double mx_snap, double my_snap) ORDER(xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2); storeobject(-1, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2,WIRE,0,0,NULL); hash_wire(XINSERT, xctx->wires-1, 1); - drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2, 0); + drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2, 0, NULL); } } else { xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1; @@ -1895,7 +1897,7 @@ void new_wire(int what, double mx_snap, double my_snap) ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2); storeobject(-1, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2,WIRE,0,0,NULL); hash_wire(XINSERT, xctx->wires-1, 1); - drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0); + drawline(WIRELAYER,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0, NULL); } xctx->prep_hi_structs = 0; if(tclgetboolvar("autotrim_wires")) trim_wires(); @@ -2129,14 +2131,14 @@ void new_line(int what) xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2; ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1); storeobject(-1, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1,LINE,xctx->rectcolor,0,NULL); - drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1, 0); + drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy1, 0, NULL); } if(xctx->nl_yy2!=xctx->nl_yy1) { xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1; xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2; ORDER(xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2); storeobject(-1, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2,LINE,xctx->rectcolor,0,NULL); - drawline(xctx->rectcolor,NOW, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0); + drawline(xctx->rectcolor,NOW, xctx->nl_xx2,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0, NULL); } } else if(xctx->manhattan_lines==2) { if(xctx->nl_yy2!=xctx->nl_yy1) { @@ -2144,21 +2146,21 @@ void new_line(int what) xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2; ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2); storeobject(-1, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2,LINE,xctx->rectcolor,0,NULL); - drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2, 0); + drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx1,xctx->nl_yy2, 0, NULL); } if(xctx->nl_xx2!=xctx->nl_xx1) { xctx->nl_xx1=xctx->nl_x1;xctx->nl_yy1=xctx->nl_y1; xctx->nl_xx2=xctx->nl_x2;xctx->nl_yy2=xctx->nl_y2; ORDER(xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2); storeobject(-1, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2,LINE,xctx->rectcolor,0,NULL); - drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2, 0); + drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy2,xctx->nl_xx2,xctx->nl_yy2, 0, NULL); } } else { xctx->nl_xx1 = xctx->nl_x1; xctx->nl_yy1 = xctx->nl_y1; xctx->nl_xx2 = xctx->nl_x2; xctx->nl_yy2 = xctx->nl_y2; ORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2); storeobject(-1, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2,LINE,xctx->rectcolor,0,NULL); - drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0); + drawline(xctx->rectcolor,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2, 0, NULL); } } xctx->nl_x1=xctx->nl_x2=xctx->mousex_snap;xctx->nl_y1=xctx->nl_y2=xctx->mousey_snap; diff --git a/src/callback.c b/src/callback.c index 8e389e6b..7128a1ba 100644 --- a/src/callback.c +++ b/src/callback.c @@ -82,7 +82,7 @@ void redraw_w_a_l_r_p_rubbers(void) } } -static void abort_operation(void) +void abort_operation(void) { xctx->no_draw = 0; tcleval("set constrained_move 0" ); @@ -292,7 +292,7 @@ static void backannotate_at_cursor_b_pos(xRect *r, Graph_ctx *gr) filledrect(c, END, 0.0, 0.0, 0.0, 0.0); drawarc(c, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); drawrect(c, END, 0.0, 0.0, 0.0, 0.0, 0); - drawline(c, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(c, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); } xctx->draw_window = save; #endif @@ -438,7 +438,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int /* check if user clicked on a wave label -> draw wave in bold */ if(event == ButtonPress && button == Button3 && edit_wave_attributes(2, i, gr)) { - draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr); /* draw data in graph box */ + draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in graph box */ return 0; } /* save mouse position when doing pan operations */ @@ -1011,7 +1011,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int } /* else if( event == ButtonRelease) */ if(need_redraw || need_all_redraw) { setup_graph_data(i, xctx->graph_flags, 0, gr); - draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr); /* draw data in each graph box */ + draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in each graph box */ } } /* for(i=0; i< xctx->rects[GRIDLAYER]; i++ */ @@ -1916,7 +1916,10 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key, if(xctx->semaphore >= 2) break; descend_symbol();break; } - if(key==XK_Insert || (key == 'I' && state == ShiftMask) ) /* insert sym */ + if(key==XK_Insert && state == ShiftMask) { + tcleval("c_toolbar display"); + } + if((key==XK_Insert && state == 0) || (key == 'I' && state == ShiftMask) ) /* insert sym */ { if(xctx->semaphore >= 2) break; start_place_symbol(mx, my); diff --git a/src/draw.c b/src/draw.c index 3abd1322..fc8b3c05 100644 --- a/src/draw.c +++ b/src/draw.c @@ -381,7 +381,7 @@ void draw_string(int layer, int what, const char *str, short rot, short flip, in ROTATION(rot, flip, x1,y1,curr_x1,curr_y1,rx1,ry1); ROTATION(rot, flip, x1,y1,curr_x2,curr_y2,rx2,ry2); ORDER(rx1,ry1,rx2,ry2); - drawline(layer, what, rx1, ry1, rx2, ry2, 0); + drawline(layer, what, rx1, ry1, rx2, ry2, 0, NULL); } pos++; a += FONTWIDTH+FONTWHITESPACE; @@ -492,9 +492,9 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, ROTATION(rot, flip, 0.0,0.0,line->x2,line->y2,x2,y2); ORDER(x1,y1,x2,y2); if(line->bus) - drawline(c,THICK, x0+x1, y0+y1, x0+x2, y0+y2, line->dash); + drawline(c,THICK, x0+x1, y0+y1, x0+x2, y0+y2, line->dash, NULL); else - drawline(c,what, x0+x1, y0+y1, x0+x2, y0+y2, line->dash); + drawline(c,what, x0+x1, y0+y1, x0+x2, y0+y2, line->dash, NULL); } for(j=0;j< symptr->polygons[layer];j++) { @@ -592,7 +592,7 @@ void draw_symbol(int what,int c, int n,int layer,short tmp_flip, short rot, x0+x1, y0+y1, text.xscale, text.yscale); #if HAS_CAIRO!=1 drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); - drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); #endif #if HAS_CAIRO==1 if( (textfont && textfont[0]) || (symptr->text[j].flags & (TEXT_BOLD | TEXT_OBLIQUE | TEXT_ITALIC))) { @@ -805,8 +805,56 @@ static void drawgrid() } } +#if !defined(__unix__) && defined(HAS_CAIRO) +static void my_cairo_drawline(cairo_t *ct, int layer, double x1, double y1, double x2, double y2, int dash) +{ + cairo_set_source_rgb(ct, + (double)xctx->xcolor_array[layer].red/65535.0, + (double)xctx->xcolor_array[layer].green/65535.0, + (double)xctx->xcolor_array[layer].blue/65535.0); + if (dash) { + double dashes[1]; + dashes[0] = dash; + cairo_set_dash(ct, dashes, 1, 0); + } + cairo_move_to(ct, x1, y1); + cairo_line_to(ct,x2, y2); + cairo_stroke(ct); /* This lines need to be here */ +} -void drawline(int c, int what, double linex1, double liney1, double linex2, double liney2, int dash) +static void my_cairo_drawpoints(cairo_t *ct, int layer, XPoint *points, int npoints) +{ + cairo_set_source_rgb(ct, + (double)xctx->xcolor_array[layer].red/65535.0, + (double)xctx->xcolor_array[layer].green/65535.0, + (double)xctx->xcolor_array[layer].blue/65535.0); + for (int i =0; iwindow, xctx->gc[c], rr[j].x1, rr[j].y1, rr[j].x2, rr[j].y2); if (xctx->draw_pixmap) XDrawLine(display, xctx->save_pixmap, xctx->gc[c], rr[j].x1, rr[j].y1, rr[j].x2, rr[j].y2); + check_cairo_drawline(ct, c, rr[j].x1, rr[j].y1, rr[j].x2, rr[j].y2, 0); } #endif i=0; @@ -873,6 +922,9 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub if(dash) { XSetLineAttributes (display, xctx->gc[c], INT_WIDTH(xctx->lw), LineSolid, CapRound, JoinRound); } + #ifndef __unix__ + check_cairo_drawline(ct, c, x1, y1, x2, y2, dash); + #endif } } @@ -894,6 +946,9 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub } if(xctx->draw_window) XDrawLine(display, xctx->window, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2); if(xctx->draw_pixmap) XDrawLine(display, xctx->save_pixmap, xctx->gc[c], (int)x1, (int)y1, (int)x2, (int)y2); + #ifndef __unix__ + check_cairo_drawline(ct, c, x1, y1, x2, y2, dash); + #endif XSetLineAttributes (display, xctx->gc[c], INT_WIDTH(xctx->lw), LineSolid, CapRound , JoinRound); } } @@ -908,6 +963,7 @@ void drawline(int c, int what, double linex1, double liney1, double linex2, doub XDrawLine(display, xctx->window, xctx->gc[c], rr[j].x1, rr[j].y1, rr[j].x2, rr[j].y2); if (xctx->draw_pixmap) XDrawLine(display, xctx->save_pixmap, xctx->gc[c], rr[j].x1, rr[j].y1, rr[j].x2, rr[j].y2); + check_cairo_drawline(ct, c, rr[j].x1, rr[j].y1, rr[j].x2, rr[j].y2, 0); } #endif i=0; @@ -1755,7 +1811,7 @@ static void set_thick_waves(int what, int wcnt, int wave_col, Graph_ctx *gr) LDA,LDA[3],LDA[2],LDA1],LDA[0] */ static void draw_graph_bus_points(const char *ntok, int n_bits, SPICE_DATA **idx_arr, - int first, int last, int wave_col, int sweep_idx, int wcnt, int n_nodes, Graph_ctx *gr) + int first, int last, int wave_col, int sweep_idx, int wcnt, int n_nodes, Graph_ctx *gr, void *ct) { int p; double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */ @@ -1785,8 +1841,8 @@ static void draw_graph_bus_points(const char *ntok, int n_bits, SPICE_DATA **idx } if(c1 >= gr->ypos1 && c1 <=gr->ypos2) { set_thick_waves(1, wcnt, wave_col, gr); - drawline(wave_col, NOW, lx1, ylow, lx2, ylow, 0); - drawline(wave_col, NOW, lx1, yhigh, lx2, yhigh, 0); + drawline(wave_col, NOW, lx1, ylow, lx2, ylow, 0, ct); + drawline(wave_col, NOW, lx1, yhigh, lx2, yhigh, 0, ct); for(p = first ; p <= last; p++) { /* calculate value of bus by adding all binary bits */ /* hex_digits = */ @@ -1803,10 +1859,10 @@ static void draw_graph_bus_points(const char *ntok, int n_bits, SPICE_DATA **idx } if(p > first && strcmp(busval, old_busval)) { /* draw transition ('X') */ - drawline(BACKLAYER, NOW, xval-x_size, yhigh, xval+x_size, yhigh, 0); - drawline(BACKLAYER, NOW, xval-x_size, ylow, xval+x_size, ylow, 0); - drawline(wave_col, NOW, xval-x_size, ylow, xval+x_size, yhigh, 0); - drawline(wave_col, NOW, xval-x_size, yhigh, xval+x_size, ylow, 0); + drawline(BACKLAYER, NOW, xval-x_size, yhigh, xval+x_size, yhigh, 0, ct); + drawline(BACKLAYER, NOW, xval-x_size, ylow, xval+x_size, ylow, 0, ct); + drawline(wave_col, NOW, xval-x_size, ylow, xval+x_size, yhigh, 0, ct); + drawline(wave_col, NOW, xval-x_size, yhigh, xval+x_size, ylow, 0, ct); /* draw hex bus value if there is enough room */ if( fabs(xval - xval_old) > hex_digits * charwidth) { draw_string(wave_col, NOW, old_busval, 2, 0, 1, 0, (xval + xval_old) * 0.5, @@ -1827,7 +1883,7 @@ static void draw_graph_bus_points(const char *ntok, int n_bits, SPICE_DATA **idx /* wcnt is the nth wave in graph, idx is the index in spice raw file */ static void draw_graph_points(int idx, int first, int last, - XPoint *point, int wave_col, int wcnt, int n_nodes, Graph_ctx *gr) + XPoint *point, int wave_col, int wcnt, int n_nodes, Graph_ctx *gr, void *ct) { int p; register double yy; @@ -1868,11 +1924,14 @@ static void draw_graph_points(int idx, int first, int last, if(xctx->draw_pixmap) { XDrawLines(display, xctx->save_pixmap, xctx->gc[wave_col], point, poly_npoints, CoordModeOrigin); } + #ifndef __unix__ + check_cairo_drawpoints(ct, wave_col, point, poly_npoints); + #endif set_thick_waves(0, wcnt, wave_col, gr); } else dbg(1, "skipping wave: %s\n", xctx->graph_names[idx]); } -static void draw_graph_grid(Graph_ctx *gr) +static void draw_graph_grid(Graph_ctx *gr, void *ct) { double deltax, startx, deltay, starty, wx,wy, dash_sizex, dash_sizey; int j, k; @@ -1908,13 +1967,13 @@ static void draw_graph_grid(Graph_ctx *gr) subwx = wx + deltax * (double)k / ((double)gr->subdivx + 1.0); if(!axis_within_range(subwx, gr->gx1, gr->gx2)) continue; if(axis_end(subwx, deltax, gr->gx2)) break; - drawline(GRIDLAYER, ADD, W_X(subwx), W_Y(gr->gy2), W_X(subwx), W_Y(gr->gy1), (int)dash_sizey); + drawline(GRIDLAYER, ADD, W_X(subwx), W_Y(gr->gy2), W_X(subwx), W_Y(gr->gy1), (int)dash_sizey, ct); } if(!axis_within_range(wx, gr->gx1, gr->gx2)) continue; if(axis_end(wx, deltax, gr->gx2)) break; /* swap order of gy1 and gy2 since grap y orientation is opposite to xorg orientation */ - drawline(GRIDLAYER, ADD, W_X(wx), W_Y(gr->gy2), W_X(wx), W_Y(gr->gy1), (int)dash_sizey); - drawline(GRIDLAYER, ADD, W_X(wx), W_Y(gr->gy1), W_X(wx), W_Y(gr->gy1) + mark_size, 0); /* axis marks */ + drawline(GRIDLAYER, ADD, W_X(wx), W_Y(gr->gy2), W_X(wx), W_Y(gr->gy1), (int)dash_sizey, ct); + drawline(GRIDLAYER, ADD, W_X(wx), W_Y(gr->gy1), W_X(wx), W_Y(gr->gy1) + mark_size, 0, ct); /* axis marks */ /* X-axis labels */ if(gr->logx) draw_string(3, NOW, dtoa(pow(10, wx) * gr->unitx), 0, 0, 1, 0, W_X(wx), gr->y2 + mark_size + 5 * gr->txtsizex, @@ -1924,8 +1983,8 @@ static void draw_graph_grid(Graph_ctx *gr) gr->txtsizex, gr->txtsizex); } /* first and last vertical box delimiters */ - drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(gr->gy2), W_X(gr->gx1), W_Y(gr->gy1), 0); - drawline(GRIDLAYER, ADD, W_X(gr->gx2), W_Y(gr->gy2), W_X(gr->gx2), W_Y(gr->gy1), 0); + drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(gr->gy2), W_X(gr->gx1), W_Y(gr->gy1), 0, ct); + drawline(GRIDLAYER, ADD, W_X(gr->gx2), W_Y(gr->gy2), W_X(gr->gx2), W_Y(gr->gy1), 0, ct); /* horizontal grid lines */ if(!gr->digital) { deltay = axis_increment(gr->gy1, gr->gy2, gr->divy, gr->logy); @@ -1940,12 +1999,12 @@ static void draw_graph_grid(Graph_ctx *gr) subwy = wy + deltay * (double)k / ((double)gr->subdivy + 1.0); if(!axis_within_range(subwy, gr->gy1, gr->gy2)) continue; if(axis_end(subwy, deltay, gr->gy2)) break; - drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(subwy), W_X(gr->gx2), W_Y(subwy), (int)dash_sizex); + drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(subwy), W_X(gr->gx2), W_Y(subwy), (int)dash_sizex, ct); } if(!axis_within_range(wy, gr->gy1, gr->gy2)) continue; if(axis_end(wy, deltay, gr->gy2)) break; - drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(wy), W_X(gr->gx2), W_Y(wy), (int)dash_sizex); - drawline(GRIDLAYER, ADD, W_X(gr->gx1) - mark_size, W_Y(wy), W_X(gr->gx1), W_Y(wy), 0); /* axis marks */ + drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(wy), W_X(gr->gx2), W_Y(wy), (int)dash_sizex, ct); + drawline(GRIDLAYER, ADD, W_X(gr->gx1) - mark_size, W_Y(wy), W_X(gr->gx1), W_Y(wy), 0, ct); /* axis marks */ /* Y-axis labels */ if(gr->logy) draw_string(3, NOW, dtoa(pow(10, wy) * gr->unity), 0, 1, 0, 1, gr->x1 - mark_size - 5 * gr->txtsizey, W_Y(wy), @@ -1956,16 +2015,16 @@ static void draw_graph_grid(Graph_ctx *gr) } } /* first and last horizontal box delimiters */ - drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(gr->gy1), W_X(gr->gx2), W_Y(gr->gy1), 0); - drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(gr->gy2), W_X(gr->gx2), W_Y(gr->gy2), 0); + drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(gr->gy1), W_X(gr->gx2), W_Y(gr->gy1), 0, ct); + drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(gr->gy2), W_X(gr->gx2), W_Y(gr->gy2), 0, ct); /* Horizontal axis (if in viewport) */ if(!gr->digital && gr->gy1 <= 0 && gr->gy2 >= 0) - drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(0), W_X(gr->gx2), W_Y(0), 0); + drawline(GRIDLAYER, ADD, W_X(gr->gx1), W_Y(0), W_X(gr->gx2), W_Y(0), 0, ct); /* Vertical axis (if in viewport) * swap order of gy1 and gy2 since grap y orientation is opposite to xorg orientation */ if(gr->gx1 <= 0 && gr->gx2 >= 0) - drawline(GRIDLAYER, ADD, W_X(0), W_Y(gr->gy2), W_X(0), W_Y(gr->gy1), 0); - drawline(GRIDLAYER, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(GRIDLAYER, ADD, W_X(0), W_Y(gr->gy2), W_X(0), W_Y(gr->gy1), 0, ct); + drawline(GRIDLAYER, END, 0.0, 0.0, 0.0, 0.0, 0, ct); bbox(END, 0.0, 0.0, 0.0, 0.0); } @@ -2139,7 +2198,7 @@ static void draw_cursor(double active_cursorx, double other_cursorx, int cursor_ int xoffs = flip ? 3 : -3; if(xx >= gr->x1 && xx <= gr->x2) { - drawline(cursor_color, NOW, xx, gr->ry1, xx, gr->ry2, 1); + drawline(cursor_color, NOW, xx, gr->ry1, xx, gr->ry2, 1, NULL); if(gr->logx) active_cursorx = pow(10, active_cursorx); if(gr->unitx != 1.0) my_snprintf(tmpstr, S(tmpstr), "%.5g%c", gr->unitx * active_cursorx , gr->unitx_suffix); @@ -2179,8 +2238,8 @@ static void draw_cursor_difference(Graph_ctx *gr) dtmp = a; a = b; b = dtmp; } yline = (ty1 + ty2) * 0.5; - if( tx1 - a > 4.0) drawline(3, NOW, a + 2, yline, tx1 - 2, yline, 1); - if( b - tx2 > 4.0) drawline(3, NOW, tx2 + 2, yline, b - 2, yline, 1); + if( tx1 - a > 4.0) drawline(3, NOW, a + 2, yline, tx1 - 2, yline, 1, NULL); + if( b - tx2 > 4.0) drawline(3, NOW, tx2 + 2, yline, b - 2, yline, 1, NULL); } } @@ -2647,7 +2706,7 @@ int find_closest_wave(int i, Graph_ctx *gr) * 4: draw x-cursor2 * 8: all drawing, if not set do only XCopyArea / x-cursor if specified */ -void draw_graph(int i, const int flags, Graph_ctx *gr) +void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct) { int wave_color = 4; char *node = NULL, *color = NULL, *sweep = NULL; @@ -2682,7 +2741,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr) clear_cairo_surface(xctx->cairo_ctx, gr->sx1, gr->sy1, sw, sh); #endif /* graph box, gridlines and axes */ - draw_graph_grid(gr); + draw_graph_grid(gr, ct); /* get data to plot */ my_strdup2(1389, &node, get_tok_value(r->prop_ptr,"node",0)); my_strdup2(1390, &color, get_tok_value(r->prop_ptr,"color",0)); @@ -2771,11 +2830,11 @@ void draw_graph(int i, const int flags, Graph_ctx *gr) if(bus_msb) { if(digital) { draw_graph_bus_points(ntok, n_bits, idx_arr, first, last, wave_color, - sweep_idx, wcnt, n_nodes, gr); + sweep_idx, wcnt, n_nodes, gr, ct); } } else { if(expression) idx = plot_raw_custom_data(sweep_idx, first, last, express); - draw_graph_points(idx, first, last, point, wave_color, wcnt, n_nodes, gr); + draw_graph_points(idx, first, last, point, wave_color, wcnt, n_nodes, gr, ct); } } poly_npoints = 0; @@ -2812,11 +2871,11 @@ void draw_graph(int i, const int flags, Graph_ctx *gr) if(bus_msb) { if(digital) { draw_graph_bus_points(ntok, n_bits, idx_arr, first, last, wave_color, - sweep_idx, wcnt, n_nodes, gr); + sweep_idx, wcnt, n_nodes, gr, ct); } } else { if(expression) idx = plot_raw_custom_data(sweep_idx, first, last, express); - draw_graph_points(idx, first, last, point, wave_color, wcnt, n_nodes, gr); + draw_graph_points(idx, first, last, point, wave_color, wcnt, n_nodes, gr, ct); } } } @@ -2892,7 +2951,7 @@ static void draw_graph_all(int flags) xRect *r = &xctx->rect[GRIDLAYER][i]; if(r->flags & 1) { setup_graph_data(i, flags, 0, &xctx->graph_struct); - draw_graph(i, flags, &xctx->graph_struct); /* draw data in each graph box */ + draw_graph(i, flags, &xctx->graph_struct, NULL); /* draw data in each graph box */ } } } @@ -3127,7 +3186,7 @@ static void draw_images_all(void) void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2, double ry2) { - #if defined(__unix__) && defined(HAS_CAIRO) + #if defined(HAS_CAIRO) char *ptr = NULL; double x1, y1, x2, y2, w, h, rw, rh, scale; char transform[150]; @@ -3158,8 +3217,26 @@ void svg_embedded_graph(FILE *fd, xRect *r, double rx1, double ry1, double rx2, xctx->draw_pixmap=1; xctx->do_copy_area=0; draw(); +#ifdef __unix__ png_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual, xctx->xrect[0].width, xctx->xrect[0].height); +#else + /* pixmap doesn't work on windows + Copy from cairo_save_sfc and use cairo + to draw in the data points to embed the graph */ + png_sfc = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, xctx->xrect[0].width, xctx->xrect[0].height); + cairo_t *ct = cairo_create(png_sfc); + cairo_set_source_surface(ct, xctx->cairo_save_sfc, 0, 0); + cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); + cairo_paint(ct); + for(int i = 0; i < xctx->rects[GRIDLAYER]; i++) { + xRect *r = &xctx->rect[GRIDLAYER][i]; + if(r->flags & 1) { + setup_graph_data(i, 8, 0, &xctx->graph_struct); + draw_graph(i, 8, &xctx->graph_struct, (void *)ct); + } + } +#endif closure.buffer = NULL; closure.size = 0; closure.pos = 0; @@ -3244,8 +3321,8 @@ void draw(void) if(xctx->enable_layer[c]) for(i=0;ilines[c];i++) { xLine *l = &xctx->line[c][i]; - if(l->bus) drawline(c, THICK, l->x1, l->y1, l->x2, l->y2, l->dash); - else drawline(c, ADD, l->x1, l->y1, l->x2, l->y2, l->dash); + if(l->bus) drawline(c, THICK, l->x1, l->y1, l->x2, l->y2, l->dash, NULL); + else drawline(c, ADD, l->x1, l->y1, l->x2, l->y2, l->dash, NULL); } if(xctx->enable_layer[c]) for(i=0;irects[c];i++) { xRect *r = &xctx->rect[c][i]; @@ -3294,7 +3371,7 @@ void draw(void) filledrect(c, END, 0.0, 0.0, 0.0, 0.0); drawarc(c, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); drawrect(c, END, 0.0, 0.0, 0.0, 0.0, 0); - drawline(c, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(c, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); } if(xctx->draw_single_layer==-1 || xctx->draw_single_layer==WIRELAYER) { if(use_hash) init_wire_iterator(&ctx, x1, y1, x2, y2); @@ -3310,15 +3387,15 @@ void draw(void) } if(xctx->wire[i].bus) { drawline(WIRELAYER, THICK, xctx->wire[i].x1,xctx->wire[i].y1, - xctx->wire[i].x2,xctx->wire[i].y2, 0); + xctx->wire[i].x2,xctx->wire[i].y2, 0, NULL); } else drawline(WIRELAYER, ADD, xctx->wire[i].x1,xctx->wire[i].y1, - xctx->wire[i].x2,xctx->wire[i].y2, 0); + xctx->wire[i].x2,xctx->wire[i].y2, 0, NULL); } update_conn_cues(1, xctx->draw_window); filledrect(WIRELAYER, END, 0.0, 0.0, 0.0, 0.0); - drawline(WIRELAYER, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(WIRELAYER, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); } if(xctx->draw_single_layer ==-1 || xctx->draw_single_layer==TEXTLAYER) { for(i=0;itexts;i++) @@ -3360,7 +3437,7 @@ void draw(void) #endif #if HAS_CAIRO!=1 drawrect(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); - drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(textlayer, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); #endif } } diff --git a/src/hilight.c b/src/hilight.c index 2f732173..6890074c 100644 --- a/src/hilight.c +++ b/src/hilight.c @@ -1800,10 +1800,10 @@ void draw_hilight_net(int on_window) if( (entry = bus_hilight_hash_lookup(xctx->wire[i].node, 0, XLOOKUP)) ) { if(xctx->wire[i].bus) drawline(get_color(entry->value), THICK, - xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2, 0); + xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2, 0, NULL); else drawline(get_color(entry->value), NOW, - xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2, 0); + xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2, 0, NULL); if(cadhalfdotsize*xctx->mooz>=0.7) { if( xctx->wire[i].end1 >1 ) { filledarc(get_color(entry->value), NOW, xctx->wire[i].x1, xctx->wire[i].y1, cadhalfdotsize, 0, 360); @@ -1839,7 +1839,7 @@ void draw_hilight_net(int on_window) filledrect(col, END, 0.0, 0.0, 0.0, 0.0); drawarc(col, END, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0); drawrect(col, END, 0.0, 0.0, 0.0, 0.0, 0); - drawline(col, END, 0.0, 0.0, 0.0, 0.0, 0); + drawline(col, END, 0.0, 0.0, 0.0, 0.0, 0, NULL); } } } diff --git a/src/scheduler.c b/src/scheduler.c index 5961f259..02e1c013 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -286,82 +286,88 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg */ if(argv[1][0] == 'a') { + if(!strcmp(argv[1],"abort_operation")) + { + cmd_found = 1; + abort_operation(); + } + if(!strcmp(argv[1],"add_symbol_pin")) { - cmd_found = 1; - unselect_all(1); - storeobject(-1, xctx->mousex_snap-2.5, xctx->mousey_snap-2.5, xctx->mousex_snap+2.5, xctx->mousey_snap+2.5, - xRECT, PINLAYER, SELECTED, "name=XXX\ndir=inout"); - xctx->need_reb_sel_arr=1; - rebuild_selected_array(); - move_objects(START,0,0,0); - xctx->ui_state |= START_SYMPIN; - Tcl_ResetResult(interp); + cmd_found = 1; + unselect_all(1); + storeobject(-1, xctx->mousex_snap-2.5, xctx->mousey_snap-2.5, xctx->mousex_snap+2.5, xctx->mousey_snap+2.5, + xRECT, PINLAYER, SELECTED, "name=XXX\ndir=inout"); + xctx->need_reb_sel_arr=1; + rebuild_selected_array(); + move_objects(START,0,0,0); + xctx->ui_state |= START_SYMPIN; + Tcl_ResetResult(interp); } if(!strcmp(argv[1],"add_graph")) { - cmd_found = 1; - unselect_all(1); - xctx->graph_lastsel = xctx->rects[GRIDLAYER]; - storeobject(-1, xctx->mousex_snap-400, xctx->mousey_snap-200, xctx->mousex_snap+400, xctx->mousey_snap+200, - xRECT, GRIDLAYER, SELECTED, - "flags=graph\n" - "y1=0\n" - "y2=2\n" - "ypos1=0\n" - "ypos2=2\n" - "divy=5\n" - "subdivy=1\n" - "unity=1\n" - "x1=0\n" - "x2=10e-6\n" - "divx=5\n" - "subdivx=1\n" - "node=\"\"\n" - "color=\"\"\n" - "dataset=-1\n" - "unitx=u\n" - "logx=0\n" - "logy=0\n" - ); - xctx->need_reb_sel_arr=1; - rebuild_selected_array(); - move_objects(START,0,0,0); - xctx->ui_state |= START_SYMPIN; - Tcl_ResetResult(interp); + cmd_found = 1; + unselect_all(1); + xctx->graph_lastsel = xctx->rects[GRIDLAYER]; + storeobject(-1, xctx->mousex_snap-400, xctx->mousey_snap-200, xctx->mousex_snap+400, xctx->mousey_snap+200, + xRECT, GRIDLAYER, SELECTED, + "flags=graph\n" + "y1=0\n" + "y2=2\n" + "ypos1=0\n" + "ypos2=2\n" + "divy=5\n" + "subdivy=1\n" + "unity=1\n" + "x1=0\n" + "x2=10e-6\n" + "divx=5\n" + "subdivx=1\n" + "node=\"\"\n" + "color=\"\"\n" + "dataset=-1\n" + "unitx=u\n" + "logx=0\n" + "logy=0\n" + ); + xctx->need_reb_sel_arr=1; + rebuild_selected_array(); + move_objects(START,0,0,0); + xctx->ui_state |= START_SYMPIN; + Tcl_ResetResult(interp); } if(!strcmp(argv[1],"add_png")) { - char str[PATH_MAX+100]; - cmd_found = 1; - unselect_all(1); - tcleval("tk_getOpenFile -filetypes { {{Png} {.png}} {{All files} *} }"); - if(tclresult()[0]) { - my_snprintf(str, S(str), "flags=image,unscaled\nalpha=0.8\nimage=%s\n", tclresult()); - storeobject(-1, xctx->mousex_snap-100, xctx->mousey_snap-100, xctx->mousex_snap+100, xctx->mousey_snap+100, - xRECT, GRIDLAYER, SELECTED, str); - xctx->need_reb_sel_arr=1; - rebuild_selected_array(); - move_objects(START,0,0,0); - xctx->ui_state |= START_SYMPIN; - } - Tcl_ResetResult(interp); + char str[PATH_MAX+100]; + cmd_found = 1; + unselect_all(1); + tcleval("tk_getOpenFile -filetypes { {{Png} {.png}} {{All files} *} }"); + if(tclresult()[0]) { + my_snprintf(str, S(str), "flags=image,unscaled\nalpha=0.8\nimage=%s\n", tclresult()); + storeobject(-1, xctx->mousex_snap-100, xctx->mousey_snap-100, xctx->mousex_snap+100, xctx->mousey_snap+100, + xRECT, GRIDLAYER, SELECTED, str); + xctx->need_reb_sel_arr=1; + rebuild_selected_array(); + move_objects(START,0,0,0); + xctx->ui_state |= START_SYMPIN; + } + Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"align")) { - cmd_found = 1; - xctx->push_undo(); - round_schematic_to_grid(tclgetdoublevar("cadsnap")); - if(tclgetboolvar("autotrim_wires")) trim_wires(); - set_modify(1); - xctx->prep_hash_inst=0; - xctx->prep_hash_wires=0; - xctx->prep_net_structs=0; - xctx->prep_hi_structs=0; - draw(); + cmd_found = 1; + xctx->push_undo(); + round_schematic_to_grid(tclgetdoublevar("cadsnap")); + if(tclgetboolvar("autotrim_wires")) trim_wires(); + set_modify(1); + xctx->prep_hash_inst=0; + xctx->prep_hash_wires=0; + xctx->prep_net_structs=0; + xctx->prep_hi_structs=0; + draw(); } else if(!strcmp(argv[1],"annotate_op")) @@ -699,7 +705,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg flags = 1 + 8 + (xctx->graph_flags & 6); } setup_graph_data(i, xctx->graph_flags, 0, &xctx->graph_struct); - draw_graph(i, flags, &xctx->graph_struct); + draw_graph(i, flags, &xctx->graph_struct, NULL); } Tcl_ResetResult(interp); } @@ -1617,7 +1623,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg if(argc==7) pos=atoi(argv[6]); storeobject(pos, x1,y1,x2,y2,LINE,xctx->rectcolor,0,NULL); save = xctx->draw_window; xctx->draw_window = 1; - drawline(xctx->rectcolor,NOW, x1,y1,x2,y2, 0); + drawline(xctx->rectcolor,NOW, x1,y1,x2,y2, 0, NULL); xctx->draw_window = save; } else xctx->ui_state |= MENUSTARTLINE; @@ -3010,7 +3016,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg xctx->prep_net_structs=0; xctx->prep_hash_wires=0; save = xctx->draw_window; xctx->draw_window = 1; - drawline(WIRELAYER,NOW, x1,y1,x2,y2, 0); + drawline(WIRELAYER,NOW, x1,y1,x2,y2, 0, NULL); xctx->draw_window = save; if(tclgetboolvar("autotrim_wires")) trim_wires(); } diff --git a/src/xschem.h b/src/xschem.h index d3f2e116..818ecae5 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1045,7 +1045,7 @@ extern int plot_raw_custom_data(int sweep_idx, int first, int last, const char * extern int calc_custom_data_yrange(int sweep_idx, const char *express, Graph_ctx *gr); extern int sch_waves_loaded(void); extern int edit_wave_attributes(int what, int i, Graph_ctx *gr); -extern void draw_graph(int i, int flags, Graph_ctx *gr); +extern void draw_graph(int i, int flags, Graph_ctx *gr, void *ct); extern int find_closest_wave(int i, Graph_ctx *gr); extern void setup_graph_data(int i, const int flags, int skip, Graph_ctx *gr); extern double timer(int start); @@ -1127,13 +1127,14 @@ extern unsigned short select_object(double mx,double my, unsigned short sel_mode extern void unselect_all(int dr); extern void select_inside(double x1,double y1, double x2, double y2, int sel); extern int Tcl_AppInit(Tcl_Interp *interp); +extern void abort_operation(void); extern int callback(const char *winpath, int event, int mx, int my, KeySym key, int button, int aux, int state); extern void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h); extern Selected find_closest_obj(double mx,double my); extern void find_closest_net_or_symbol_pin(double mx,double my, double *x, double *y); -extern void drawline(int c, int what, double x1,double y1,double x2,double y2, int dash); +extern void drawline(int c, int what, double x1,double y1,double x2,double y2, int dash, void *ct); extern void draw_string(int layer,int what, const char *str, short rot, short flip, int hcenter, int vcenter, double x1, double y1, double xscale, double yscale); extern void draw_symbol(int what,int c, int n,int layer, diff --git a/src/xschem.tcl b/src/xschem.tcl index 3614544b..0de626e5 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -583,6 +583,10 @@ proc load_recent_file {} { -icon warning -parent . -type ok } } + set hash $c_toolbar::c_t(hash) + if { [info exists c_toolbar::c_t_$hash]} { + array set c_toolbar::c_t [array get c_toolbar::c_t_$hash] + } } } @@ -616,6 +620,21 @@ proc write_recent_file {} { return } puts $fd "set recentfile {$recentfile}" + + if {[info exists c_toolbar::c_t]} { + set hash $c_toolbar::c_t(hash) + set c_toolbar::c_t(time) [clock seconds] + array set c_toolbar::c_t_$hash [array get c_toolbar::c_t] + foreach i [info vars c_toolbar::c_t_*] { + ## old (~3 months) recent components will expire + if { [info exists [subst $i](time)]} { + if { [clock seconds] - [set [subst $i](time)] < 7500000} { + puts $fd "array set $i {[array get $i]}" + } + # puts "Age: [expr {[clock seconds] - [set [subst $i](time)]}]" + } + } + } close $fd } @@ -2101,6 +2120,127 @@ proc is_xschem_file {f} { return $ret } +## Recent component toolbar +namespace eval c_toolbar { + # Create a variable inside the namespace + variable c_t + set c_t(w) .c_t + set c_t(update) 1 + set c_t(hash) [hash_string $XSCHEM_LIBRARY_PATH] + + proc create {} { + variable c_t + if { ![info exists c_t(n)]} { + set c_t(n) 20 + set c_t(top) 0 + for {set i 0} {$i < $c_t(n)} {incr i} { + set c_t($i,text) " " + set c_t($i,command) {} + set c_t($i,file) {} + } + } + } + + proc cleanup {} { + variable c_t + if {![info exists c_t(n)]} return + set j 0 + set n $c_t(n) + set top $c_t(top) + for { set i $top} {1} {} { + if { $j } { + set k [expr {$i - $j}] + set c_t($k,text) $c_t($i,text) + set c_t($k,command) $c_t($i,command) + set c_t($k,file) $c_t($i,file) + } + set f [abs_sym_path $c_t($i,file)] + if {![file exists $f]} { + incr j + } + set i [expr {($i + 1) % $n} ] + if {$i == $top} break + if {$j} { + set c_t($i,text) " " + set c_t($i,command) {} + set c_t($i,file) {} + } + } + } + + proc display {} { + variable c_t + create + set w $c_t(w) + set n $c_t(n) + cleanup + if { [winfo exists $w]} { + for {set i 0} {$i < $n} {incr i} { + destroy $w.b$i + } + } else { + toplevel $w + wm geometry $w +[winfo rootx .]+[expr {[winfo rooty .] + 100}] + wm title $w "Recent" + } + set i $c_t(top) + while {1} { + button $w.b$i -text $c_t($i,text) -pady 0 -padx 0 -command $c_t($i,command) + pack $w.b$i -side top -fill x + set i [expr {($i + 1) % $n}] + if { $i == $c_t(top) } break + } + update + set height [winfo height $w] + wm minsize $w 70 $height + wm maxsize $w 9999 $height + } + + proc add {f} { + variable c_t + create + if { $c_t(update) } { + set found 0 + for { set i 0} { $i < $c_t(n)} { incr i} { + if { [string first "xschem place_symbol {$f}" $c_t($i,command)] >=0} { + set found 1 + } + } + if {$found} return + set i [expr { ($c_t(top)-1) % $c_t(n) } ];# last element + set c_t($i,file) $f + set c_t($i,command) " + xschem abort_operation + set c_toolbar::c_t(update) 0 + xschem place_symbol {$f} + " + set c_t($i,text) [file tail [file rootname $f]] + set c_t(top) $i + } + set c_t(update) 1 + } +} + +proc c_toolbar {what {f {}}} { + upvar #0 c_toolbar::c_t c_t + set w $c_t(w) + if {$what eq {create}} { + c_toolbar::create + } elseif {$what eq {add}} { + c_toolbar::create + c_toolbar::add $f + } elseif {$what eq {update}} { + if {[winfo exists $w]} { + c_toolbar::display + } + } elseif {$what eq {display}} { + c_toolbar::display + } elseif {$what eq {destroy}} { + destroy $w + } +} +## end Recent component toolbar + proc myload_set_colors1 {} { global myload_files1 dircolor for {set i 0} { $i< [.dialog.l.paneleft.list index end] } { incr i} { @@ -2200,6 +2340,19 @@ proc load_file_dialog_up {dir} { } } + +proc hash_string {s} { + set hash 5381 + set len [string length $s] + for {set i 0} { $i < $len} { incr i} { + set c [string index $s $i] + set ascii [scan $c %c] + set hash [expr {($hash + ($hash << 5) + $ascii)%4294967296} ] + } + return $hash +} + + proc load_file_dialog {{msg {}} {ext {}} {global_initdir {INITIALINSTDIR}} {loadfile {1}} {confirm_overwrt {1}} {initialf {}}} { global myload_index1 myload_files2 myload_files1 myload_retval myload_dir1 pathlist OS @@ -4605,13 +4758,13 @@ proc set_tab_names {{mod {}}} { } proc raise_dialog {parent window_path } { - if {[winfo exists .dialog] && [winfo ismapped .dialog] && [winfo ismapped $parent] && - [wm stackorder .dialog isbelow $parent ]} { - raise .dialog $window_path - } - if {[winfo exists .graphdialog] && [winfo ismapped .graphdialog] && [winfo ismapped $parent] && - [wm stackorder .graphdialog isbelow $parent ]} { - raise .graphdialog $window_path + set ct $c_toolbar::c_t(w) ;# recent component toolbar + + foreach i ".dialog .graphdialog $ct" { + if {[winfo exists $i] && [winfo ismapped $i] && [winfo ismapped $parent] && + [wm stackorder $i isbelow $parent ]} { + raise $i $window_path + } } } @@ -5019,6 +5172,8 @@ proc build_widgets { {topwin {} } } { $topwin.menubar.file.menu add command -label "Open Most Recent" \ -command {xschem load [lindex "$recentfile" 0]} -accelerator {Ctrl+Shift+O} + $topwin.menubar.file.menu add command -label "Recent components browser" \ + -command {c_toolbar display} -accelerator {Shift+Insert} $topwin.menubar.file.menu add command -label "Save" -command "xschem save" -accelerator {Ctrl+S} toolbar_add FileSave "xschem save" "Save File" $topwin $topwin.menubar.file.menu add command -label "Merge" -command "xschem merge" -accelerator {Shift+B}