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