📄 sscr.c
字号:
/* Copyright (c) 2000 Kevin Sullivan <nite@gis.net> * * Please refer to the COPYRIGHT file for more information. */#include <stdio.h>#include <string.h>#include <ncurses.h>#include <stdlib.h>#include <ctype.h>#include <sys/time.h>#include "defines.h"#include "colors.h"#include "codes.h"#include "scheck.h"#include "nap.h"#include "winio.h"#include "sscr.h"#include "lists.h"#include "alias.h"#include "status_line.h"#ifdef MEMWATCH #include "memwatch.h"#endifextern char *conns[];extern ssearch_t *search; /* search result list */extern int srch; /* 1 while search in progress */extern info_t info;/* Command-line-related variables from winio.c */extern cmds_t *ccmd;extern char cbuf[];extern int curr;extern int curx;/* curses windows and global state for search screen */WINDOW *swin;int cy; /* item number aligned with first line on screen */int num; /* item that the cursor is on */int lk; /* 0 if status line should be set to filename */int max; /* number of search results */int showconn; /* show connection speed? */int showping; /* show ping? (Note this will only be shown, by default, if pings are actually available) */int showuser; /* show user nickname? */int showbrate; /* show bitrate? */int showlength; /* show length? */int showfreq; /* show frequency? */int showsize; /* show size? */char lastsort; /* indicates what the most recent sort key was */int usercols; /* width of longest user name *//* initialize result screen state. Note: this only needs to be called when a new list of search results was generated, not each time we switch to the result screen. This way, the state will be preserved while switching back and forth between screens */void resetsscr(void){ ssearch_t *cur; char *defaults; cy = 1; /* note search items are numbered starting from 1 */ num = 1; lastsort = 0; /* determine number of items in search list, and maximum size of username */ max = 0; usercols = 4; list_forall(cur, search) { max++; if (strlen(cur->nick) > usercols) usercols = strlen(cur->nick); } showconn = 0; showping = 0; showuser = 0; showbrate = 0; showlength = 0; showfreq = 0; showsize = 0; defaults = getval("sdefaults"); if (!defaults) defaults = "blsp"; while (*defaults) { shandlechar(*defaults); defaults++; } /* turn off display of connection speed and/or pings if the information is not available */ showconn = (showconn && search && search->conn != -1) ? 1 : 0; showping = (showping && search && search->ping > -2) ? 1 : 0; /* reset screen and cursor to first item (after possible sorting!) */ cy = 1; num = 1;}/* turn on result screen */void searchscr(void){ sock_t *sk; sk = findsock("input"); if (sk) { sk->func = sinput; } swin = newwin("sscr", LINES, 0, 0, 0); wbkgdset(swin, COLOR_PAIR(CPW)); keypad(swin, TRUE); werase(swin); sl_set("Use F1 or 'q' to return to the main screen. 'h' for help."); lk = 1; plist();}/* turn off result screen */void endsearchscr(){ delwin(swin);}/* print result screen */void plist(){ int j, ln=0, min, sec, col, titlecols; ssearch_t *cur; float mb; char *t=NULL; if (screen != RESULT_SCREEN) return; if (srch) { werase(swin); mvwprintw(swin, LINES/2, (COLS-29)/2, "Waiting for search results..."); sl_draw(); wrefresh(swin); return; } if (!search) { werase(swin); mvwprintw(swin, LINES/2, (COLS-25)/2, "No search results to list"); sl_draw(); wrefresh(swin); return; } if (num > max) num = max; if (cy > max) cy = max-(LINES-3)+1; if (cy < 1) cy = 1; if (num >= (LINES-3)+cy) /* screen follows cursor */ { cy = num-(LINES-3)+1; } if (num < cy) { cy = num; } /* decide how many columns to use for filenames (=titlecols) */ titlecols = COLS - 1; titlecols -= 8*showbrate; titlecols -= 9*showlength; titlecols -= (3+usercols)*showuser; titlecols -= 12*showconn; titlecols -= 7*showping; titlecols -= 8*showfreq; switch (showsize) { case 1: titlecols -= 9; break; case 2: titlecols -= 12; break; case 0: default: break; } if (titlecols < 14) titlecols = 14; werase(swin); msprintf(&t, "Filename (total = %d)", max); if (strlen(t) > titlecols) t[titlecols]=0; mvwprintw(swin, 0, 0, "%s", t); wmove(swin, 1, 0); whline(swin, ACS_HLINE, COLS); col = titlecols; if (showbrate) { mvwprintw(swin, 0, col+3, "BRate"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 8; } if (showlength) { mvwprintw(swin, 0, col+3, "Length"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 9; } switch (showsize) { case 1: mvwprintw(swin, 0, col+3, "MBytes"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 9; break; case 2: mvwprintw(swin, 0, col+3, " Bytes"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 12; break; case 0: default: break; } if (showfreq) { mvwprintw(swin, 0, col+3, "Freq"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 8; } if (showuser) { mvwprintw(swin, 0, col+3, "User"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 3+usercols; } if (showconn) { mvwprintw(swin, 0, col+3, "Speed"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 12; } if (showping) { mvwprintw(swin, 0, col+3, "Ping"); wmove(swin, 0, col+1); wvline(swin, ACS_VLINE, LINES-1); col += 7; } /* find cy'th element of the list (remember list macros count from 0, but cy counts from 1 */ list_nth(cur, search, cy-1); for (j=cy, ln=0; cur && ln < LINES-3; j++, ln++, cur=cur->next) { if (num == j) { if (!lk) { sl_set(quote(cur->rfn)); } wattron(swin, COLOR_PAIR(1)|A_BOLD); wmove(swin, ln+2, 0); whline(swin, ' ', COLS); } msprintf(&t, "%i) %s", j, cur->song); if (strlen(t) > titlecols) t[titlecols]=0; mvwprintw(swin, ln+2, 0, "%s", t); col = titlecols; if (showbrate) { mvwprintw(swin, ln+2, col+3, "%4i", cur->brate); if (num==j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col+=8; } if (showlength) { min = cur->time/60; sec = cur->time%60; mvwprintw(swin, ln+2, col+3, "%3i:%02i", min, sec); if (num==j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col+=9; } switch (showsize) { case 1: mb = ((float)cur->sz)/1048576.0; mvwprintw(swin, ln+2, col+3, "%6.02f", mb); if (num == j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col += 9; break; case 2: mvwprintw(swin, ln+2, col+3, "%9d", cur->sz); if (num == j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col += 12; break; case 0: default: break; } if (showfreq) { mvwprintw(swin, ln+2, col+3, "%5i", cur->freq); if (num==j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col+=8; } if (showuser) { mvwprintw(swin, ln+2, col+3, "%s", cur->nick); if (num==j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col+=3+usercols; } if (showconn) { mvwprintw(swin, ln+2, col+3, cur->conn != -1 ? conns[cur->conn] : "N/A"); if (num==j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col+=12; } if (showping) { mvwprintw(swin, ln+2, col+3, cur->ping>=0 ? "%4i" : " N/A", cur->ping); if (num==j) { wmove(swin, ln+2, col+1); wvline(swin, ACS_VLINE, 1); } col+=7; } if (num == j) wattroff(swin, COLOR_PAIR(1)|A_BOLD); } /* end for j */ sl_draw(); drw(swin); if (t) free(t);}/* handle input on result screen */int sinput(WINDOW *win, sock_t *m){ chtype cbuf = 0; WINDOW *w = swin; cbuf = wgetch(w); if (cbuf == '\e') { /* ESC */ cbuf = wgetch(w); if (cbuf == ERR) return(1); else cbuf+=128; } if (!sl_handle_keystroke(cbuf)) shandlechar(cbuf); plist(); return(1);}/* handle key stroke on result screen */int shandlechar(chtype ch){ sock_t *sk; ssearch_t *cur, *a, *b; int r; const char *help = "HELP - use <right> and <left> to scroll this information. " "<up> and <down> to move cursor. <return> to download item. " "q to return to main screen. " "F1-F3 or M-1 thru M-3 to switch between screens. " "<tab> to switch between results and dl/ul screens. " "<space> to enter a new search. " "'/' to goto main screen and start a command. " "l/b/m/f/u/s/p/a/n to toggle information displayed. " "N/D/L/B/M/F/U/S/P to sort. h for help."; switch (ch) { case KEY_F(1): /* F1 */ case 128 + '1': /* M-1 */ case 'q': switchtoscreen(MAIN_SCREEN); break; case KEY_F(3): /* F3 */ case 128 + '3': /* M-3 */ case '\t': /* Tab */ switchtoscreen(DLUL_SCREEN); break; case '/': ccmd = NULL; strcpy(cbuf, "/"); curr = 0; curx = strlen(cbuf); switchtoscreen(MAIN_SCREEN); break; case 'h': case 'H': sl_set(help); lk = 1; break; case KEY_UP: /* Up */ num--; if (num <= 0) num = 1; lk = 0; break; case KEY_DOWN: /* Down */ num++; lk = 0; break; case KEY_PPAGE: /* PgUp */ case 5: /* Ctrl-E */ case 16: /* Ctrl-P */ if (nvar_default("cursorfollowsscreen", 0)) { if (cy<=1) { sl_set("Beginning of search results"); lk = 1; } else { /* one screen up, cursor follows screen */ cy -= LINES-4; if (cy<1) { cy = 1; } if (num >= (LINES-3)+cy) { num = cy+(LINES-3)-1; } lk = 0; } } else { /* screen follows cursor policy */ if (num <= 1) { sl_set("Beginning of search results"); lk = 1; } else { num -= LINES-4; if (num <= 0) num = 1; lk = 0; } } break; case KEY_NPAGE: /* PgDn */ case 4: /* Ctrl-D */ case 14: /* Ctrl-N */ case 22: /* Crtl-V */ if (nvar_default("cursorfollowsscreen", 0)) { if (cy>=max-(LINES-3)+1) { sl_set("End of search results"); lk = 1; } else { /* one screen down, cursor follows screen */ cy += LINES-4; if (cy>max-(LINES-3)+1) { cy = max-(LINES-3)+1; } if (num < cy) { num = cy; } lk = 0; } } else { /* screen follows cursor policy */ if (num>=max) { sl_set("End of search results"); lk = 1; } else { num += LINES-4; lk = 0; } } break; case 12: /* Ctrl-L */ clearok(swin, 1); wrefresh(swin); break; case '\n': if (search) { lk = 1; list_nth(cur, search, num-1); if (cur) { sk = findsock("server"); if (sk) { r = requestdownload(sk->fd, cur); switch(r) { case 0: sl_sprintf("Getting %s", cur->song); wp(wchan, "* Getting \"%s\" from %s\n", cur->song, cur->nick); break; case 1: case 2: sl_sprintf("Queued %s", cur->song); wp(wchan, "* Queued download of \"%s\" from %s\n", cur->song, cur->nick); break; case 3: sl_sprintf("Remotely queued %s", cur->song); wp(wchan, "* Remotely queued download of \"%s\" from %s\n", cur->song, cur->nick); break; case -1: sl_sprintf("Already getting %s", cur->song); break; case -2: sl_sprintf("Already queued %s", cur->song); break; case -3: sl_set("Can't get a file from yourself!"); break; default: break; } } else /* !sk */ { sl_set("Not connected to server"); } } else /* !cur */ { sl_set("Error: No matching item in search list??"); } } /* end if(search) */ break; case 'l': showlength = 1-showlength; break; case 'b': showbrate = 1-showbrate; break; case 'm': showsize = (showsize + 1) % 3; break; case 'f': showfreq = 1-showfreq; break; case 'u': showuser = 1-showuser; break; case 's': showconn = 1-showconn; break; case 'p': showping = 1-showping; break; case 'a': showlength = showbrate = showfreq = 1; showconn = showping = showuser = 1; showsize = showsize ? showsize : 1; break; case 'n': showlength = showbrate = showsize = showfreq = 0; showconn = showping = showuser = 0; break; case 'N': /* various ways to sort */ case 'D': case 'L': case 'B': case 'M': case 'F': case 'U': case 'S': case 'P': /* remember which item the cursor was on */ list_nth(cur, search, num-1); if (ch == lastsort) { /* reverse? */ list_reverse(ssearch_t, search); } else { /* sort */ lastsort = ch; /* this looks awful, but list_mergesort is a fairly large macro, and expanding it 7 times would probably be a worse option */ list_mergesort(ssearch_t, search, a, b, (ch=='N' && strcasecmp(a->song, b->song) <= 0) || (ch=='D' && strcasecmp(a->rfn, b->rfn) <= 0) || (ch=='L' && a->time <= b->time) || (ch=='B' && a->brate <= b->brate) || (ch=='M' && a->sz <= b->sz) || (ch=='F' && a->freq <= b->freq) || (ch=='U' && strcasecmp(a->nick, b->nick) <= 0) || (ch=='S' && a->conn <= b->conn) || (ch=='P' && (b->ping == -1 || (a->ping != -1 && a->ping <= b->ping))) ); } /* put the cursor back where it was */ if (cur) { list_index(search, num, a, a==cur); num++; if (num >= (LINES-3)+cy || num < cy) { cy = num-(LINES-3)/2; if (cy<1) cy = 1; } } break; default: break; } return(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -