/******************************************************************** * $Author: lindner $ * $Revision: 1.3 $ * $Date: 1993/01/06 21:01:40 $ * $Source: /home/mudhoney/GopherSrc/release1.11/gopher/RCS/manager.c,v $ * $State: Exp $ * * Paul Lindner, University of Minnesota CIS. * * Copyright 1991, 1992 by the Regents of the University of Minnesota * see the file "Copyright" in the distribution for conditions of use. ********************************************************************* * MODULE: manager.c * Procedures to manage the screen. ********************************************************************* * Revision History: * $Log: manager.c,v $ * Revision 1.3 1993/01/06 21:01:40 lindner * Improved behaviour when executing an item by typing it's number * The arrow and screen are updated to reflect the item being * retrieved. * * Revision 1.2 1993/01/05 22:31:57 lindner * Fixed display problems with directory title searching. * * Revision 1.1 1992/12/10 23:32:16 lindner * gopher 1.1 release * * Revision 1.1 1992/12/10 06:16:51 lindner * Initial revision * * *********************************************************************/ #include "gopher.h" #define MENULINE(x) (x)+3 /* If any gophers to display (screen can be blank), count the number of pages. If there is a remainder greater than zero, add one page */ #define PAGECALC(x,y) (y) ? (x/y) + ((x%y)>0) : 1 /* ** Draw the title on the top */ void Draw_Banner() { standout(); CURcenterline(CursesScreen,VERSIONline, 0); standend(); } /* ** Draw the status line */ void Draw_Status(textline) char *textline; { move(LINES-1, 0); clrtoeol(); mvaddstr(LINES-1, 0, "Press "); standout(); addstr("?"); standend(); addstr(" for Help, "); standout(); addstr("q"); standend(); addstr(" to Quit, "); standout(); addstr("u"); standend(); addstr(" to go up a menu"); clrtoeol(); mvaddch(LINES-1, COLS-strlen(textline)-2, ' '); addstr(textline); } /* ** Man is this ugly. */ void Display_Dir_Page(gopherdir, iNewLine, nNewPage, nMaxPages, iPageLen, iLastPageLen) GopherDirObj *gopherdir; int iNewLine; int nNewPage, nMaxPages, iPageLen, iLastPageLen; { int i, iLoop, iOffset; char temp[1024]; char *c, *d; int m, n, type, max; /*** Clear the screen and redraw the top line **/ clear(); Draw_Banner(); /** Draw the menu **/ iLoop = (nNewPage == nMaxPages) && iLastPageLen ? iLastPageLen : iPageLen; for (i= 0, iOffset = (nNewPage-1) * iPageLen; i (c-d))) { n = c - d; strncpy(temp, d, n); strcpy(temp + n, ".."); strcat(temp, d + (m + n - max)); printw(" %s", temp); } else { /** Trunc it.. **/ strcpy(temp, d); temp[max] ='\0'; printw(" %s..", temp); } } switch(type) { case A_DIRECTORY: addch('/'); break; case A_CSO: addstr(" "); break; case A_TN3270: addstr(" <3270>"); break; case A_TELNET: addstr(" "); break; case A_INDEX: addstr(" "); break; case A_SOUND: addstr(" <)"); /** It's supposed to look like a speaker! **/ break; case A_FILE: addch('.'); break; case A_PCBIN: addstr(" "); break; case A_UNIXBIN: addstr(" "); break; case A_IMAGE: case A_GIF: addstr(" "); break; case A_MACHEX: addstr(" "); break; } } } /* scline - Screen line relocator. * Returns the line resulting from choice */ int scline( iOldGopher, iNewGopher, gophersdir) int iOldGopher; /* Which gopher previously displayed */ int iNewGopher; /* New gopher to be displayed */ GopherDirObj *gophersdir; { int iPageLen, iLastPageLen; /* Length of normal, final pages */ int nMaxPages, nNewPage, nOldPage; /* Natural numbers */ int iOldLine, iNewLine; /* Screen locations */ char sPagenum[40]; int iMaxGophers; iMaxGophers = GDgetNumitems(gophersdir); if (iNewGopher==0) iNewGopher = GDgetNumitems(gophersdir); if ((iNewGopher > iMaxGophers)) iNewGopher = 1; iPageLen = LINES-6; /* Number of menu lines possible per page */ nMaxPages = PAGECALC(iMaxGophers, iPageLen); /* Total number of pages */ nOldPage = PAGECALC(iOldGopher, iPageLen); nNewPage = PAGECALC(iNewGopher, iPageLen); if ((nNewPage < 1) || (nNewPage > nMaxPages)) /* It won't work , make*/ return(iOldGopher); /* no changes */ iLastPageLen = iMaxGophers % iPageLen; /* Lines on last page */ iOldLine = iOldGopher - ((nOldPage-1)*iPageLen);/* Old Screen location */ iNewLine = iNewGopher - ((nNewPage-1)*iPageLen);/* New Screen location */ if ((iNewLine < 0) || (iNewLine > iPageLen)) return(iOldGopher); if (nOldPage != nNewPage) { Display_Dir_Page(gophersdir, iNewLine, nNewPage, nMaxPages, iPageLen, iLastPageLen); CURcenterline(CursesScreen,GDgetTitle(gophersdir), 2); /*** Draw the title ***/ } sprintf(sPagenum, " Page: %d/%d", nNewPage, nMaxPages); Draw_Status(sPagenum); mvaddstr(MENULINE(iOldLine), 1, " "); mvaddstr(MENULINE(iNewLine), 1, "-->"); refresh(); return(iNewGopher); } /* ** This routine draws a numbered menu ** from a gopherdirobj ** ** It returns the number that the user selected, or it returns ** zero if the user decided to cancel. ** */ int GetMenu(gd, typedchar, redisplay) GopherDirObj *gd; /** where the items are **/ int *typedchar; boolean redisplay; { int ch; /* Input character */ int iItem; /* Display line */ static int iNewItem=1; char sLinenum[5]; /* Used when going to a specific line */ BOOLEAN menudone = FALSE; int numitems; /** variables for searching **/ char search1[100]; char *search2; int sfound; int i; search1[0] = '\0'; /* search string will be remembered so init now */ numitems = GDgetNumitems(gd); iItem = -1; iNewItem = GDgetCurrentItem(gd); if (redisplay == TRUE) { iItem = scline(iItem, iNewItem, gd); /*** Draw the title ***/ CURcenterline(CursesScreen,GDgetTitle(gd), 2); move(3+iNewItem,4); /* Move to the last line that we were sitting on */ refresh(); } else iItem = GDgetCurrentItem(gd); while (menudone == FALSE) { ch = CURgetch(CursesScreen); switch(ch) { case 'j': case '\016': case KEY_DOWN: iNewItem = iItem + 1; /* Advance down the page */ break; case 'k': case '\020': /*** For those emacs dudes **/ case KEY_UP: iNewItem = iItem - 1; /* Back up */ break; case '+': /** Like in elm **/ case '>': /** Like in nn **/ case ' ': /** Like in the pager ***/ case KEY_NPAGE: /*** Go down a page ***/ iNewItem = iItem + (LINES -6); if (iNewItem > numitems) iNewItem = numitems; break; case '-': case '<': case KEY_PPAGE: case 'b': /*** Like in the pager ***/ /*** Go up a page ***/ iNewItem = iItem - (LINES - 6); if ( iNewItem < 0 ) iNewItem = 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': sLinenum[0] = (char) ch; sLinenum[1] = '\0'; if (CUROldGetOneOption(CursesScreen, "View item number: ", sLinenum) <0) { scline(iItem, iNewItem, gd); break; } if (atoi(sLinenum) <= numitems) iNewItem = atoi(sLinenum); /* Jump */ else { CURBeep(CursesScreen); break; } scline(-1, iNewItem, gd); if (iNewItem > 0 && iNewItem <= GDgetNumitems(gd)) { *typedchar = '\n'; GDsetCurrentItem(gd, iNewItem); return(iItem); } break; case '/': case 'n': sfound = 0; if (search1[0] == '\0' && ch == 'n') { CursesErrorMsg("Use '/' to define a search first..."); iItem = scline(-1,iItem, gd); break; } if (search1[0] == '\0' || ch == '/') if (CURGetOneOption(CursesScreen, "Search directory titles for", search1)<0) { iItem = scline(-1,iItem, gd); break; } if (strlen(search1) == 0) { iItem = scline(-1, iItem, gd); break; } /* * Start searching from next item */ for (i=iItem; i < numitems && sfound==0; i++) { search2 = GSgetTitle(GDgetEntry(gd, i)); if (strcasestr(search2, search1) != NULL ) { iNewItem = i+1; sfound = 1; } } /* if it wasn't found after the current line start from the beginning again */ for ( i= 0 ; i < iItem && sfound==0;i++) { search2 = GSgetTitle(GDgetEntry(gd,i)); if (strcasestr(search2,search1) != NULL ) { iNewItem = i+1; sfound = 1; } } if (sfound == 0) { search1[0] = '\0'; CURBeep(CursesScreen); CursesErrorMsg("Search failed..."); } if (ch != 'n') iItem = scline(-1, iNewItem, gd); break; case '\0': break; default: menudone = TRUE; if (ch == KEY_LEFT || ch == 'h' || ch == '\002') ch = 'u'; if (ch == KEY_RIGHT || ch == 'l' || ch == '\006') ch = '\n'; *typedchar = ch; GDsetCurrentItem(gd, iItem); return(iItem); } iItem = scline(iItem, iNewItem, gd); refresh(); } *typedchar = ch; GDsetCurrentItem(gd, iItem); return(iItem); }