#include "cursesview.h" #include #include #include #include #define CURSESWIN_COUNT 3 // Global variable shared by all threads to say "finish current operation and go away" extern int end; // window updated by cursesUpdateSliceDump callback from "worker" thread, with a mutex for prevent fuzzy concurrent updates WINDOW *winUpdateSliceDump=NULL; static pthread_mutex_t ncursesWriteMutex = PTHREAD_MUTEX_INITIALIZER; address_t sliceDumpBegin, sliceDumpEnd, sliceDumpMin, sliceDumpMax; // Helpers declaration (below the interesting code of this file) int cursesInit(WINDOW *wins[], PANEL *panels[], int count); void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count); void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice); //void printInMiddle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]); void cursesMainLoop(slices_evt_t *slicesEvt) { char msg[255]; int ch, i; WINDOW *wins[CURSESWIN_COUNT]; PANEL *panels[CURSESWIN_COUNT]; #ifdef NCURSES_MOUSE_VERSION int dispatched, res; int (*mouseEventListener)(MEVENT mevent, WINDOW *winDebug); MEVENT mevent; PANEL *p; #endif cursesInit(wins, panels, CURSESWIN_COUNT); sliceDumpBegin=sliceDumpMin=slicesEvt->data->min; sliceDumpEnd=sliceDumpMax=slicesEvt->data->max; wattron(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4)); mvwprintw(wins[CURSESWIN_COUNT-1], 1, 0, "F2:Exit F5:Zoom left F6:Unzoom left F7:Unzoom right F8:Zoom right"); // wattroff(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4)); // update_panels(); doupdate(); /* Enable worker listener */ //FIXME : check pointers ? winUpdateSliceDump=wins[1]; slicesEvt->eventListener=cursesUpdateSliceDump; while((ch = getch()) != KEY_F(2)) { pthread_mutex_lock(&ncursesWriteMutex); switch(ch) { // Zoom handling //FIXME : Do something less stupid. Try to reuse mouse event zoom code for keyboard case KEY_F(5): sliceDumpEnd=(sliceDumpBegin+sliceDumpEnd)/2; break; case KEY_F(6): sliceDumpBegin=sliceDumpMin; break; case KEY_F(7): sliceDumpEnd=sliceDumpMax; break; case KEY_F(8): sliceDumpBegin=(sliceDumpBegin+sliceDumpEnd)/2; break; // Panel focus case '1': case '2': case '3': i=ch-'0'; if (i>0 && i<=CURSESWIN_COUNT) { top_panel(panels[i-1]); update_panels(); } break; #ifdef NCURSES_MOUSE_VERSION case KEY_MOUSE: // Seems to have a mouse event res = getmouse(&mevent); if ( res == OK ) { // Try to find in which panel (search first in top-level panel and go down) p=NULL; while ( ( p=panel_below(p) ) != NULL) { if ( wenclose(panel_window(p), mevent.y, mevent.x) ) { break; } } // If we found a panel, dispatch the event if a listener is set if (p != NULL) { mouseEventListener=(int (*)(MEVENT mevent, WINDOW *winDebug)) panel_userptr(p); dispatched=(mouseEventListener==NULL)?0:mouseEventListener(mevent, wins[0]); if ( ! dispatched ) { // If no listener or event not consumed, use the default behavior : set the panel on top if BUTTON1_CLICKED if ( (mevent.bstate & BUTTON1_CLICKED) == BUTTON1_CLICKED) { top_panel(p); } } } } break; #endif default: sprintf(msg, "Unhandled key ch==0x%x", ch); wattron(wins[0], COLOR_PAIR(4)); mvwprintw(wins[0], 2, 0, msg); } doupdate(); sprintf(msg, "Viewing [%lli-%lli] of [%lli-%lli] working region ", sliceDumpBegin, sliceDumpEnd, slicesEvt->data->min, slicesEvt->data->max); wattron(wins[0], COLOR_PAIR(4)); mvwprintw(wins[0], 1, 0, msg); pthread_mutex_unlock(&ncursesWriteMutex); } pthread_mutex_lock(&(slicesEvt->eventListenerMutex)); slicesEvt->eventListener=NULL; pthread_mutex_unlock(&(slicesEvt->eventListenerMutex)); end=1; cursesUnInit(wins, panels, CURSESWIN_COUNT); } // TODO : faire une structure avec tous les éléments graphiques utiles au listener et tout passer par référence de la mainloop à ce listener #define DEFAULT_ZOOM_FACTOR 2.f int winSlicesMouseEventListener(MEVENT mevent, WINDOW *winDebug) { bool resb; int pX, pY, maxX, maxY; address_t delta; float pos; // For debugging char buf[255]; pY=mevent.y; pX=mevent.x; resb=wmouse_trafo(winUpdateSliceDump, &pY, &pX, false); if ( resb == TRUE ) { getmaxyx(winUpdateSliceDump, maxY, maxX); // First ligne (pY) is line 1 but first char (pX) is char 0 so we have to translate Y coords by -1 pos=(0.0f+(pY-1)*maxX+pX)/((maxY-1)*maxX-1); delta=sliceDumpEnd-sliceDumpBegin; sliceDumpBegin+=delta*pos/DEFAULT_ZOOM_FACTOR*(DEFAULT_ZOOM_FACTOR-1); sliceDumpEnd-=delta*(1-pos)/DEFAULT_ZOOM_FACTOR*(DEFAULT_ZOOM_FACTOR-1); } /* // Debug code sprintf(buf, "Debug : pX==%i, pY==%i, maxX==%i, maxY==%i, pos==%f, sliceDumpEnd==%lli, sliceDumpBegin=%lli, delta==%lli", pX, pY, maxX, maxY, pos, sliceDumpEnd, sliceDumpBegin, delta); wattron(winDebug, COLOR_PAIR(4)); mvwprintw(winDebug, 2, 0, buf); */ return 1; } int cursesInit(WINDOW *wins[], PANEL *panels[], int count) { int screenH, screenW; #ifdef NCURSES_MOUSE_VERSION char buf[255]; mmask_t mmask; #endif /* Initialize curses */ initscr(); start_color(); raw(); keypad(stdscr, TRUE); noecho(); #ifdef NCURSES_MOUSE_VERSION mmask = mousemask(REPORT_MOUSE_POSITION|BUTTON1_CLICKED, NULL); #endif /* Initialize all the colors */ init_pair(1, COLOR_WHITE, COLOR_BLACK); init_pair(2, COLOR_WHITE, COLOR_BLUE); init_pair(3, COLOR_BLUE, COLOR_BLACK); init_pair(4, COLOR_CYAN, COLOR_BLACK); /* Initialize windows and panels */ getmaxyx(stdscr, screenH, screenW); if ( screenH < 8 || screenW < 40 ) return 1; makeWin(wins+0, panels+0, 3 , screenW, 0 , 0, "Menu"); makeWin(wins+1, panels+1, screenH-6 , screenW, 3 , 0, "Main Win"); makeWin(wins+2, panels+2, 2 , screenW, screenH-3 , 0, "Commands"); /* Set up the user pointers to the next panel set_panel_userptr(panels[0], panels[1]); set_panel_userptr(panels[1], panels[2]); set_panel_userptr(panels[2], panels[0]); */ set_panel_userptr(panels[1], winSlicesMouseEventListener); #ifdef NCURSES_MOUSE_VERSION sprintf(buf, "Debug infos : mmask=%lx", mmask); mvprintw(LINES - 3, 0, buf); #endif /* Update the stacking order. 2nd panel will be on top */ update_panels(); return 0; } void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count) { int i; for (i=0;idata, &blockSize, charCount, sliceDumpBegin, sliceDumpEnd); if (toPrint != NULL) { attron(COLOR_PAIR(4)); mvwprintw(winUpdateSliceDump, 1, 0, toPrint); // attroff(COLOR_PAIR(4)); update_panels(); doupdate(); free(toPrint); } /* sprintf(toPrint, "%c - %p %p", strProgress[progress], slicesEvt, modifiedSlice); progress=(progress+1)%strlen(strProgress); */ pthread_mutex_unlock(&ncursesWriteMutex); } /* void printInMiddle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) { int length, x, y; float temp; if(win == NULL) win = stdscr; getyx(win, y, x); if(startx != 0) x = startx; if(starty != 0) y = starty; if(width == 0) width = 80; length = strlen(string); temp = (width - length)/ 2; x = startx + (int)temp; wattron(win, color); mvwprintw(win, y, x, "%s", string); wattroff(win, color); refresh(); } */ void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]) { int i; *win = newwin(h, w, y, x); mvwprintw(*win, 0, 0, "%s", title); mvwchgat(*win, 0, 0, -1, A_BOLD, 2, NULL); for(i=1;i