1 /***************************************************************************
2                           CursesScreen.cxx - a curses based Screen implementation
3                              -------------------
4     begin                : Thu Mar  1 13:15:18 IST 2001
5     copyright            : (C) 2001 by Arie Tal
6     email                : tal_arie@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 
22 #include "CursesScreen.h"
23 #include <curses.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <signal.h>
30 
31 static int isVtTerminal = 0 ;
32 
33 static WINDOW *
34 windowHandles[MAX_WINDOWS] ;
35 
36 static WINDOW *
37 borderHandles[MAX_WINDOWS] ;
38 
39 static CursesWindow *windowRecords[MAX_WINDOWS] ;
40 
41 #define TO_WIN(x) (x)
42 
43 static int
44 nextWindowToAllocate = 0 ;
45 
46 #define MAIN 1
47 #define BOLD 2
48 #define BOLD2 3
49 #define BOLD3 4
50 
51 #define MAIN_COLOR COLOR_WHITE
52 #define BOLD_COLOR COLOR_WHITE
53 #define BOLD2_COLOR COLOR_YELLOW
54 #define BOLD3_COLOR COLOR_GREEN
55 
56 #define DEFAULT_BACKGROUND_COLOR COLOR_BLACK
57 #define REVERSE_BACKGROUND_COLOR COLOR_WHITE
58 
CursesScreen(int hebrew_location,int alternate_hebrew_location)59 CursesScreen::CursesScreen(int hebrew_location,
60 			   int alternate_hebrew_location) :
61 			   Screen(hebrew_location, alternate_hebrew_location) {
62    initscr() ;
63    start_color() ;
64    init_pair(MAIN,MAIN_COLOR,DEFAULT_BACKGROUND_COLOR) ;
65    init_pair(BOLD,BOLD_COLOR,DEFAULT_BACKGROUND_COLOR) ;
66    init_pair(BOLD2,BOLD2_COLOR,DEFAULT_BACKGROUND_COLOR) ;
67    init_pair(BOLD3,BOLD3_COLOR,DEFAULT_BACKGROUND_COLOR) ;
68 //   cbreak() ;
69 //Just returned it:
70    cbreak() ;
71    raw() ;
72    noecho() ;
73    nonl() ;
74    intrflush(stdscr, FALSE); keypad(stdscr,TRUE);
75    meta(stdscr,TRUE) ;
76    colors_enabled = has_colors() ;
77 
78    windowHandles[nextWindowToAllocate] = stdscr ;
79    windowRecords[nextWindowToAllocate] = new CursesWindow(0,0,0,0,0) ;
80    borderHandles[nextWindowToAllocate++] = 0 ;
81 
82    ENTER=KEY_ENTER ; REFRESH=KEY_REFRESH ;
83    F1=KEY_F(1) ; HELP=KEY_HELP ;
84    F2=KEY_F(2) ; SAVE=KEY_SAVE ;
85    F6=KEY_F(6) ; GOTO_LINE=F6 ;
86    F4=KEY_F(4) ;
87    F5=KEY_F(5) ;
88    F7=KEY_F(7) ;
89    F8=KEY_F(8) ;
90    F9=KEY_F(9) ;
91    F10=KEY_F(10) ;
92    F11=KEY_F(11) ;
93    F12=KEY_F(12) ;
94    TAB = 9 ;
95    LEFT=KEY_LEFT ; RIGHT=KEY_RIGHT ;
96    UP=KEY_UP; DOWN=KEY_DOWN; SUSPEND=KEY_SUSPEND ; F3=KEY_F(3) ; EXIT=KEY_EXIT ;
97    BACKSPACE=KEY_BACKSPACE ; DC=KEY_DC ; DL=KEY_DL ; NPAGE=KEY_NPAGE ;
98    PPAGE=KEY_PPAGE ; END=KEY_END ; HOME=KEY_HOME ;
99    special_separator = SPECIAL_SEPARATOR ;
100    left_end_mark = LEFT_END_MARK ;
101    right_end_mark = RIGHT_END_MARK ;
102    if (getenv("TERM"))
103      if (!strncmp(getenv("TERM"),"vt",2)) isVtTerminal=1 ;
104 }
105 
~CursesScreen()106 CursesScreen::~CursesScreen()
107 {
108    refresh() ;
109    endwin() ;
110 }
111 
112 void
TemporaryExit(int justrefresh,char * cmd,int background)113 CursesScreen::TemporaryExit(int justrefresh, char *cmd, int background)
114 {
115    Erase() ;
116    if ((!justrefresh) && (!cmd))
117       MVAddStr(5,3,"Type  exit  to return to editing") ;
118      refresh() ;
119      endwin() ;
120    if (!justrefresh) {
121      if (!cmd)
122       system("$SHELL") ;
123      else if (!background) {
124        fprintf(stderr,"Executing %s:\n\n",cmd) ;
125        system(cmd) ;
126        fprintf(stderr,"\n\nPress Enter to return to editing...\n") ;
127        getchar() ;
128      } else {
129         char *buf = new char[strlen(cmd)+10] ;
130         sprintf(buf,"%s &", cmd) ;
131         system(buf) ;
132         delete buf ;
133      }
134    }
135      initscr() ;
136      //   cbreak() ;
137      start_color() ;
138    init_pair(MAIN,MAIN_COLOR,DEFAULT_BACKGROUND_COLOR) ;
139    init_pair(BOLD,BOLD_COLOR,DEFAULT_BACKGROUND_COLOR) ;
140    init_pair(BOLD2,BOLD2_COLOR,DEFAULT_BACKGROUND_COLOR) ;
141    init_pair(BOLD3,BOLD3_COLOR,DEFAULT_BACKGROUND_COLOR) ;
142      raw() ;
143      noecho() ;
144      nonl() ;
145      intrflush(stdscr, FALSE); keypad(stdscr,TRUE);
146      // HERE WE HAVE TO RECONSTRUCT ALL THE WINDOW STRUCTURES!!!!!
147 
148      windowHandles[0] = stdscr ;
149      Erase() ;
150      int tmp = nextWindowToAllocate ;
151      nextWindowToAllocate = 1 ;
152      for (int i=1 ; i<tmp; i++)
153        if (windowRecords[i]) {
154 	 allocateNewWindow(windowRecords[i]->nlines,
155 			   windowRecords[i]->ncols,
156 			   windowRecords[i]->begin_y,
157 			   windowRecords[i]->begin_x,
158 			   windowRecords[i]->border) ;
159          Erase(i) ;
160        }
161        else
162 	 nextWindowToAllocate++ ;
163 }
164 
165 void
Suspend()166 CursesScreen::Suspend()
167 {
168    Erase() ;
169    refresh() ;
170    endwin() ;
171    printf("Suspended\n") ;
172    kill(getpid(), SIGSTOP) ;
173    initscr() ;
174      //   cbreak() ;
175     start_color() ;
176    init_pair(MAIN,MAIN_COLOR,DEFAULT_BACKGROUND_COLOR) ;
177    init_pair(BOLD,BOLD_COLOR,DEFAULT_BACKGROUND_COLOR) ;
178    init_pair(BOLD2,BOLD2_COLOR,DEFAULT_BACKGROUND_COLOR) ;
179    init_pair(BOLD3,BOLD3_COLOR,DEFAULT_BACKGROUND_COLOR) ;
180      raw() ;
181      noecho() ;
182      nonl() ;
183      intrflush(stdscr, FALSE); keypad(stdscr,TRUE);
184      // HERE WE HAVE TO RECONSTRUCT ALL THE WINDOW STRUCTURES!!!!!
185 
186      windowHandles[0] = stdscr ;
187      Erase() ;
188      int tmp = nextWindowToAllocate ;
189      nextWindowToAllocate = 1 ;
190      for (int i=1 ; i<tmp; i++)
191        if (windowRecords[i]) {
192 	 allocateNewWindow(windowRecords[i]->nlines,
193 			   windowRecords[i]->ncols,
194 			   windowRecords[i]->begin_y,
195 			   windowRecords[i]->begin_x,
196 			   windowRecords[i]->border) ;
197          Erase(i) ;
198        }
199        else
200 	 nextWindowToAllocate++ ;
201 }
202 
GetMaxYX(int * y,int * x,int wh)203 void CursesScreen::GetMaxYX(int *y, int *x, int wh)
204 {
205    // in curses getmaxyx is a macro which sets y and x to the size of the
206    // screen
207    getmaxyx(stdscr,*y, *x) ;
208    rows = *y ; cols = *x ;
209    getmaxyx(TO_WIN(windowHandles[wh]),*y, *x) ;
210 //   if (wh) (*y)++ ;
211 }
212 
Erase(int wh,int flip_reverse)213 void CursesScreen::Erase(int wh, int flip_reverse)
214 {
215    werase(TO_WIN(windowHandles[wh])) ;
216 }
217 
Refresh(int wh)218 void CursesScreen::Refresh(int wh)
219 {
220 //   touchwin(stdscr) ;
221    wrefresh(TO_WIN(windowHandles[wh])) ;
222 }
223 
MVAddStr(int y,int x,char * str,int wh)224 void CursesScreen::MVAddStr(int y, int x, char *str,int wh)
225 {
226    if (colors_enabled) {
227    if (current_attr & REVERSE_ATTR) wattron(TO_WIN(windowHandles[wh]),A_REVERSE) ;
228      else wattroff(TO_WIN(windowHandles[wh]),A_REVERSE) ;
229 
230      if ((current_attr == NORMAL_ATTR) || (current_attr == REVERSE_ATTR)) wattrset(TO_WIN(windowHandles[wh]),COLOR_PAIR(MAIN)) ;
231      if (current_attr & BOLD_ATTR) wattrset(TO_WIN(windowHandles[wh]),COLOR_PAIR(BOLD)) ;
232      if (current_attr & BOLD2_ATTR) wattrset(TO_WIN(windowHandles[wh]),COLOR_PAIR(BOLD2)) ;
233      if (current_attr & BOLD3_ATTR) wattrset(TO_WIN(windowHandles[wh]),COLOR_PAIR(BOLD3)) ;
234    if (current_attr & REVERSE_ATTR) wattron(TO_WIN(windowHandles[wh]),A_REVERSE) ;
235      else wattroff(TO_WIN(windowHandles[wh]),A_REVERSE) ;
236      wattron(TO_WIN(windowHandles[wh]),A_BOLD) ;
237    if ((current_attr & BOLD_ATTR) || (current_attr == NORMAL_ATTR)) wattron(TO_WIN(windowHandles[wh]),A_BOLD) ;
238 //     else wattroff(TO_WIN(windowHandles[wh]),A_BOLD) ;
239    } else {
240    if (current_attr & REVERSE_ATTR) wattron(TO_WIN(windowHandles[wh]),A_REVERSE) ;
241      else wattroff(TO_WIN(windowHandles[wh]),A_REVERSE) ;
242      if (isVtTerminal) {
243        if (current_attr & BOLD2_ATTR) wattron(TO_WIN(windowHandles[wh]),A_UNDERLINE) ;
244          else wattroff(TO_WIN(windowHandles[wh]),A_UNDERLINE) ;
245      } else {
246        if (current_attr & BOLD2_ATTR) wattron(TO_WIN(windowHandles[wh]),A_UNDERLINE) ;
247          else wattroff(TO_WIN(windowHandles[wh]),A_UNDERLINE) ;
248      }
249      if (current_attr == NORMAL_ATTR) wattroff(TO_WIN(windowHandles[wh]),A_UNDERLINE | A_REVERSE) ;
250    }
251    mvwaddstr(TO_WIN(windowHandles[wh]), y, x, str) ;
252    if (wh==0)
253       wmove(TO_WIN(windowHandles[wh]), hardy, hardx) ;
254    if (colors_enabled) {
255        wattrset(TO_WIN(windowHandles[wh]),PAIR_NUMBER(MAIN)) ;
256        wattroff(TO_WIN(windowHandles[wh]),PAIR_NUMBER(BOLD)) ;
257        wattroff(TO_WIN(windowHandles[wh]),PAIR_NUMBER(BOLD2)) ;
258        wattroff(TO_WIN(windowHandles[wh]),PAIR_NUMBER(BOLD3)) ;
259        wattroff(TO_WIN(windowHandles[wh]),A_REVERSE) ;
260    }
261 }
262 
Move(int y,int x,int wh)263 void CursesScreen::Move(int y, int x, int wh)
264 {
265    wmove(TO_WIN(windowHandles[wh]),y,x) ;
266    hardy = y + windowRecords[wh]->begin_y ;
267    hardx = x + windowRecords[wh]->begin_x ;
268 }
269 
DeleteLn(int wh)270 void CursesScreen::DeleteLn(int wh)
271 {
272    wdeleteln(TO_WIN(windowHandles[wh])) ;
273 }
274 
InsertLn(int wh)275 void CursesScreen::InsertLn(int wh)
276 {
277    winsertln(TO_WIN(windowHandles[wh])) ;
278 }
279 
GetCh()280 int CursesScreen::GetCh()
281 {
282    int c=getch() ;
283    if ((c=='') && isVtTerminal) c='' ;
284    return c ;
285 }
286 
KeyName(int c)287 char *CursesScreen::KeyName(int c)
288 {
289    static char buff[20] ;
290    if ((c>0) && (c < 27)) {
291      sprintf(buff,"^%c",'@'+c) ;
292      return buff ;
293    } else if (c == 27) {
294       sprintf(buff,"ESC-") ;
295       return buff ;
296    } else
297     if (c == ENTER)
298         sprintf(buff,"ENTER") ;
299     else
300     if (c == REFRESH)
301         sprintf(buff,"REFRESH") ;
302     else
303     if (c == F1)
304         sprintf(buff,"F1") ;
305     else
306     if (c == HELP)
307         sprintf(buff,"HELP") ;
308     else
309     if (c == F2)
310         sprintf(buff,"F2") ;
311     else
312     if (c == LEFT)
313         sprintf(buff,"LEFT") ;
314     else
315     if (c == RIGHT)
316         sprintf(buff,"RIGHT") ;
317     else
318     if (c == SAVE)
319         sprintf(buff,"SAVE") ;
320     else
321     if (c == F3)
322         sprintf(buff,"F3") ;
323     else
324     if (c == EXIT)
325         sprintf(buff,"EXIT") ;
326     else
327     if (c == F4)
328         sprintf(buff,"F4") ;
329     else
330     if (c == F5)
331         sprintf(buff,"F5") ;
332     else
333     if (c == F6)
334         sprintf(buff,"F6") ;
335     else
336     if (c == GOTO_LINE)
337         sprintf(buff,"GOTO_LINE") ;
338     else
339     if (c == F7)
340         sprintf(buff,"F7") ;
341     else
342     if (c == F8)
343         sprintf(buff,"F8") ;
344     else
345     if (c == F9)
346         sprintf(buff,"F9") ;
347     else
348     if (c == F10)
349         sprintf(buff,"F10") ;
350     else
351     if (c == F11)
352         sprintf(buff,"F11") ;
353     else
354     if (c == F12)
355         sprintf(buff,"F12") ;
356     else
357     if (c == UP)
358         sprintf(buff,"UP") ;
359     else
360     if (c == DOWN)
361         sprintf(buff,"DOWN") ;
362     else
363     if (c == SUSPEND)
364         sprintf(buff,"SUSPEND") ;
365     else
366     if (c == BACKSPACE)
367         sprintf(buff,"BACKSPACE") ;
368     else
369     if (c == DC)
370         sprintf(buff,"DEL_CHAR") ;
371     else
372     if (c == DL)
373         sprintf(buff,"DEL_LINE") ;
374     else
375     if (c == NPAGE)
376         sprintf(buff,"NEXT_PAGE") ;
377     else
378     if (c == PPAGE)
379         sprintf(buff,"PREVIOUS_PAGE") ;
380     else
381     if (c == END)
382         sprintf(buff,"END") ;
383     else
384     if (c == HOME)
385         sprintf(buff,"HOME") ;
386     else
387         sprintf(buff,"%c", c) ;
388    return buff ;
389 }
390 
391 int
allocateNewWindow(int nlines,int ncols,int begin_y,int begin_x,int brdr)392 CursesScreen::allocateNewWindow(int nlines, int ncols, int begin_y, int begin_x, int brdr)
393 {
394   windowRecords[nextWindowToAllocate] =
395     new CursesWindow(nlines,ncols,begin_y, begin_x, brdr) ;
396 
397   int sizey, sizex ;
398   GetMaxYX(&sizey, &sizex) ;
399   if (nlines <= 0) nlines = sizey+nlines ;
400   if (ncols <=0) ncols = sizex+ncols ;
401 
402   if (!brdr) {
403     windowHandles[nextWindowToAllocate] = subwin(stdscr,nlines,ncols,begin_y,begin_x) ;
404     borderHandles[nextWindowToAllocate] = 0 ;
405   } else {
406     borderHandles[nextWindowToAllocate] =
407       subwin(stdscr,nlines+2,ncols+2,begin_y-1, begin_x-1) ;
408     wattrset(borderHandles[nextWindowToAllocate], A_REVERSE) ;
409     wborder(TO_WIN(borderHandles[nextWindowToAllocate]),0,0,0,0,0,0,0,0) ;
410 //    touchwin(stdscr) ;
411     wrefresh(borderHandles[nextWindowToAllocate]) ;
412     windowHandles[nextWindowToAllocate] =
413       subwin(stdscr,nlines,ncols,begin_y, begin_x) ;
414   }
415   return nextWindowToAllocate++ ;
416 }
417 
418 void
closeAllocatedWindow(int wh)419 CursesScreen::closeAllocatedWindow(int wh)
420 {
421   if (TO_WIN(windowHandles[wh])) {
422     delwin(TO_WIN(windowHandles[wh])) ;
423     if (borderHandles[wh])
424       delwin(borderHandles[wh]) ;
425     windowHandles[wh] = 0 ;
426     borderHandles[wh] = 0 ;
427     windowRecords[wh]=0 ;
428   }
429 }
430 
431 
432 void
setWindowTopTitle(char * str,int wh)433 CursesScreen::setWindowTopTitle(char *str, int wh)
434 {
435    if (!wh) return ;
436 
437    if (!borderHandles[wh]) return ;
438 
439    int curattr = current_attr ;
440    wattrset(borderHandles[wh],A_REVERSE) ;
441    int x, y ;
442    GetMaxYX(&y,&x,wh) ;
443    mvwaddstr(borderHandles[wh],0,
444          (x - strlen(str)) / 2,
445             str) ;
446 //   touchwin(stdscr) ;
447    wrefresh(borderHandles[wh]) ;
448    SetAttr(curattr) ;
449 }
450