tin  2.4.4
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.4.4.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

global.c
Go to the documentation of this file.
1 /*
2  * Project : tin - a Usenet reader
3  * Module : global.c
4  * Author : Jason Faultless <jason@altarstone.com>
5  * Created : 1999-12-12
6  * Updated : 2005-10-19
7  * Notes : Generic navigation and key handling routines
8  *
9  * Copyright (c) 1999-2020 Jason Faultless <jason@altarstone.com>
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution.
22  *
23  * 3. Neither the name of the copyright holder nor the names of its
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 
41 #ifndef TIN_H
42 # include "tin.h"
43 #endif /* !TIN_H */
44 #ifndef TCURSES_H
45 # include "tcurses.h"
46 #endif /* !TCURSES_H */
47 
48 /*
49  * Local prototypes
50  */
51 #ifdef USE_CURSES
52  static void do_scroll(int jump);
53 #endif /* USE_CURSES */
54 
55 
56 /*
57  * Calculate the first and last objects that will appear on the current screen
58  * based on the current position and the max available
59  */
60 void
62  void)
63 {
64  if (currmenu->max == 0) {
65  currmenu->first = 0;
66  currmenu->curr = -1;
67  return;
68  }
69 
70  if (currmenu->curr >= currmenu->max)
71  currmenu->curr = currmenu->max - 1;
72  else if (currmenu->curr < -1)
73  currmenu->curr = -1;
74 
75  if (currmenu->curr < currmenu->first || currmenu->curr > currmenu->first + NOTESLINES - 1) /* current selection is out of screen */
77 }
78 
79 
80 void
82  void)
83 {
84  if (!currmenu->max)
85  return;
86 
87  if (currmenu->curr - 1 < currmenu->first && currmenu->curr != 0) {
88  currmenu->first--;
89 #ifdef USE_CURSES
90  do_scroll(-1);
92 #else
93  currmenu->redraw();
94 #endif /* USE_CURSES */
95  }
96  if (currmenu->curr == 0) {
98 
99  if (currmenu->max - 1 >= NOTESLINES) {
100  currmenu->curr = currmenu->max - 1;
101  currmenu->redraw();
102  } else
103  move_to_item(currmenu->max - 1);
104  } else
105  move_to_item(currmenu->curr - 1);
106 }
107 
108 
109 void
111  void)
112 {
113  if (!currmenu->max)
114  return;
115 
116  if (currmenu->curr + 1 > currmenu->first + NOTESLINES - 1 && currmenu->curr + 1 < currmenu->max) {
117  currmenu->first++;
118 #ifdef USE_CURSES
119  do_scroll(1);
121 #else
122  currmenu->redraw();
123 #endif /* USE_CURSES */
124  }
125  move_to_item((currmenu->curr + 1 >= currmenu->max) ? 0 : (currmenu->curr + 1));
126 }
127 
128 
129 void
131  void)
132 {
133  int scroll_lines;
134 
135  if (!currmenu->max)
136  return;
137 
138  if (currmenu->curr == currmenu->first) {
139  scroll_lines = (tinrc.scroll_lines == -2) ? NOTESLINES / 2 : NOTESLINES;
140  if (currmenu->first == 0) {
141  /* wrap around */
142  currmenu->first = MAX(0, currmenu->max - scroll_lines);
143  currmenu->curr = currmenu->max - 1;
144  } else {
145  currmenu->first = MAX(0, currmenu->first - scroll_lines);
147  }
148  currmenu->redraw();
149  } else
151 }
152 
153 
154 void
156  void)
157 {
158  int scroll_lines;
159 
160  if (!currmenu->max)
161  return;
162 
163  if (currmenu->curr == currmenu->max - 1) {
164  /* wrap around */
165  currmenu->first = 0;
166  currmenu->curr = 0;
167  currmenu->redraw();
168  } else {
169  scroll_lines = (tinrc.scroll_lines == -2) ? NOTESLINES / 2 : NOTESLINES;
170  if (currmenu->first + scroll_lines >= currmenu->max)
171  move_to_item(currmenu->max - 1);
172  else {
173  currmenu->first += scroll_lines;
175  currmenu->redraw();
176  }
177  }
178 }
179 
180 
181 void
183  void)
184 {
185  if (currmenu->max)
186  move_to_item(0);
187 }
188 
189 
190 void
192  void)
193 {
194  if (currmenu->max)
195  move_to_item(currmenu->max - 1);
196 }
197 
198 
199 void
201  int ch,
202  const char *prompt)
203 {
204  int num;
205 
206  clear_message();
207 
208  if ((num = prompt_num(ch, prompt)) == -1) {
209  clear_message();
210  return;
211  }
212 
213  if (--num < 0) /* index from 0 (internal) vs. 1 (user) */
214  num = 0;
215 
216  if (num >= currmenu->max)
217  num = currmenu->max - 1;
218 
219  move_to_item(num);
220 }
221 
222 
223 /*
224  * Move the on-screen pointer & internal pointer variable to a new position
225  */
226 void
228  int n)
229 {
230  if (currmenu->curr == n)
231  return;
232 
234  erase_arrow();
235 
236  if ((currmenu->curr = n) < 0)
237  currmenu->curr = 0;
238  clear_message();
239 
240  if (n >= currmenu->first && n < currmenu->first + NOTESLINES)
241  currmenu->draw_arrow();
242  else
243  currmenu->redraw();
244 }
245 
246 
247 /*
248  * scroll the screen one line down
249  * the selected item is only moved if it is scrolled off the screen
250  */
251 void
253  void)
254 {
255  if (!currmenu->max || currmenu->first + NOTESLINES >= currmenu->max)
256  return;
257 
258  currmenu->first++;
259 #ifdef USE_CURSES
260  do_scroll(1);
262  stow_cursor();
263  if (currmenu->curr < currmenu->first)
264  move_to_item(currmenu->curr + 1);
265 #else
266  if (currmenu->curr < currmenu->first)
267  currmenu->curr++;
268  currmenu->redraw();
269 #endif /* USE_CURSES */
270 }
271 
272 
273 /*
274  * scroll the screen one line up
275  * the selected item is only moved if it is scrolled off the screen
276  */
277 void
279  void)
280 {
281  if (!currmenu->max || currmenu->first == 0)
282  return;
283 
284  currmenu->first--;
285 #ifdef USE_CURSES
286  do_scroll(-1);
288  stow_cursor();
290  move_to_item(currmenu->curr - 1);
291 #else
293  currmenu->curr--;
294  currmenu->redraw();
295 #endif /* USE_CURSES */
296 }
297 
298 
299 #ifdef USE_CURSES
300 /* TODO: merge with options_menu.c:do_scroll() and move to tcurses.c */
301 /* scroll the screen 'jump' lines down or up (if 'jump' < 0) */
302 static void
303 do_scroll(
304  int jump)
305 {
306  scrollok(stdscr, TRUE);
307  MoveCursor(INDEX_TOP, 0);
309  ScrollScreen(jump);
310  SetScrollRegion(0, LINES - 1);
311  scrollok(stdscr, FALSE);
312 }
313 #endif /* USE_CURSES */
314 
315 
316 /*
317  * Handle mouse clicks. We simply map the event to a return
318  * keymap code that will drop through to call the correct function
319  */
322  t_function (*left_action) (void),
323  t_function (*right_action) (void))
324 {
325  int INDEX_BOTTOM = INDEX_TOP + NOTESLINES;
326 
327  switch (xmouse) {
328  case MOUSE_BUTTON_1:
329  case MOUSE_BUTTON_3:
330  if (xrow < INDEX_TOP || xrow >= INDEX_BOTTOM)
331  return GLOBAL_PAGE_DOWN;
332 
333  erase_arrow();
335  currmenu->draw_arrow();
336 
337  if (xmouse == MOUSE_BUTTON_1)
338  return right_action();
339  break;
340 
341  case MOUSE_BUTTON_2:
342  if (xrow < INDEX_TOP || xrow >= INDEX_BOTTOM)
343  return GLOBAL_PAGE_UP;
344 
345  return left_action();
346 
347  default:
348  break;
349  }
350  return NOT_ASSIGNED;
351 }
352 
353 
356  t_function (*left_action) (void),
357  t_function (*right_action) (void),
358  t_function (*mouse_action) (
359  t_function (*left_action) (void),
360  t_function (*right_action) (void)),
361  const struct keylist keys)
362 {
363 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
364  wint_t ch = ReadWch();
365 #else
366  int ch = ReadCh();
367 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
368  t_function func = NOT_ASSIGNED;
369 
370  switch (ch) {
371  case ESC: /* common arrow keys */
372 # ifdef HAVE_KEY_PREFIX
373  case KEY_PREFIX:
374 # endif /* HAVE_KEY_PREFIX */
375  switch (get_arrow_key((int) ch)) {
376  case KEYMAP_UP:
377  func = GLOBAL_LINE_UP;
378  break;
379 
380  case KEYMAP_DOWN:
381  func = GLOBAL_LINE_DOWN;
382  break;
383 
384  case KEYMAP_LEFT:
385  func = left_action();
386  break;
387 
388  case KEYMAP_RIGHT:
389  func = right_action();
390  break;
391 
392  case KEYMAP_PAGE_UP:
393  func = GLOBAL_PAGE_UP;
394  break;
395 
396  case KEYMAP_PAGE_DOWN:
397  func = GLOBAL_PAGE_DOWN;
398  break;
399 
400  case KEYMAP_HOME:
401  func = GLOBAL_FIRST_PAGE;
402  break;
403 
404  case KEYMAP_END:
405  func = GLOBAL_LAST_PAGE;
406  break;
407 
408  case KEYMAP_MOUSE:
409  if (mouse_action)
410  func = mouse_action(left_action, right_action);
411  break;
412 
413  default:
414  break;
415  }
416  break;
417 
418  default:
419  func = key_to_func(ch, keys);
420  break;
421  }
422  return func;
423 }
424 
425 
426 /*
427  * bug/gripe/comment mailed to author
428  */
429 void
431  void)
432 {
433  mail_bug_report();
434  ClearScreen();
435  currmenu->redraw();
436 }
MOUSE_BUTTON_3
#define MOUSE_BUTTON_3
Definition: tin.h:2111
KEYMAP_END
#define KEYMAP_END
Definition: tin.h:1073
erase_arrow
void erase_arrow(void)
Definition: screen.c:352
handle_keypad
t_function handle_keypad(t_function(*left_action)(void), t_function(*right_action)(void), t_function(*mouse_action)(t_function(*left_action)(void), t_function(*right_action)(void)), const struct keylist keys)
Definition: global.c:355
GLOBAL_PAGE_DOWN
@ GLOBAL_PAGE_DOWN
Definition: keymap.h:200
INDEX_TOP
#define INDEX_TOP
Definition: tin.h:1008
key_to_func
t_function key_to_func(const char key, const struct keylist keys)
Definition: keymap.c:97
KEYMAP_RIGHT
#define KEYMAP_RIGHT
Definition: tin.h:1069
ESC
#define ESC
Definition: keymap.h:140
ClearScreen
void ClearScreen(void)
Definition: curses.c:410
move_down
void move_down(void)
Definition: global.c:110
tinrc
struct t_config tinrc
Definition: init.c:191
KEYMAP_HOME
#define KEYMAP_HOME
Definition: tin.h:1072
prompt_item_num
void prompt_item_num(int ch, const char *prompt)
Definition: global.c:200
SetScrollRegion
void SetScrollRegion(int topline, int bottomline)
Definition: curses.c:490
MoveCursor
void MoveCursor(int row, int col)
Definition: curses.c:441
tcurses.h
t_menu::max
int max
Definition: tin.h:2007
tin.h
GLOBAL_LAST_PAGE
@ GLOBAL_LAST_PAGE
Definition: keymap.h:192
MAX
#define MAX(a, b)
Definition: tin.h:802
top_of_list
void top_of_list(void)
Definition: global.c:182
KEYMAP_LEFT
#define KEYMAP_LEFT
Definition: tin.h:1068
t_menu::draw_item
void(* draw_item)(int item)
Definition: tin.h:2011
global_mouse_action
t_function global_mouse_action(t_function(*left_action)(void), t_function(*right_action)(void))
Definition: global.c:321
KEYMAP_MOUSE
#define KEYMAP_MOUSE
Definition: tin.h:1076
xrow
int xrow
Definition: init.c:122
GLOBAL_LINE_DOWN
@ GLOBAL_LINE_DOWN
Definition: keymap.h:194
HpGlitch
#define HpGlitch(func)
Definition: tcurses.h:176
set_first_screen_item
void set_first_screen_item(void)
Definition: global.c:61
scroll_up
void scroll_up(void)
Definition: global.c:278
GLOBAL_LINE_UP
@ GLOBAL_LINE_UP
Definition: keymap.h:195
MOUSE_BUTTON_2
#define MOUSE_BUTTON_2
Definition: tin.h:2110
stow_cursor
void stow_cursor(void)
Definition: screen.c:59
t_function
enum defined_functions t_function
Definition: keymap.h:373
bug_report
void bug_report(void)
Definition: global.c:430
currmenu
t_menu * currmenu
Definition: init.c:165
GLOBAL_FIRST_PAGE
@ GLOBAL_FIRST_PAGE
Definition: keymap.h:190
ReadCh
int ReadCh(void)
Definition: curses.c:1110
t_menu::redraw
void(* redraw)(void)
Definition: tin.h:2009
move_to_item
void move_to_item(int n)
Definition: global.c:227
KEYMAP_PAGE_DOWN
#define KEYMAP_PAGE_DOWN
Definition: tin.h:1071
move_up
void move_up(void)
Definition: global.c:81
KEYMAP_PAGE_UP
#define KEYMAP_PAGE_UP
Definition: tin.h:1070
t_menu::curr
int curr
Definition: tin.h:2006
t_menu::draw_arrow
void(* draw_arrow)(void)
Definition: tin.h:2010
keylist
Definition: keymap.h:386
get_arrow_key
int get_arrow_key(int prech)
Definition: curses.c:961
FALSE
#define FALSE
Definition: bool.h:70
prompt_num
int prompt_num(int ch, const char *prompt)
Definition: prompt.c:65
GLOBAL_PAGE_UP
@ GLOBAL_PAGE_UP
Definition: keymap.h:201
scroll_down
void scroll_down(void)
Definition: global.c:252
xmouse
int xmouse
Definition: init.c:122
t_menu::first
int first
Definition: tin.h:2008
page_down
void page_down(void)
Definition: global.c:155
page_up
void page_up(void)
Definition: global.c:130
ScrollScreen
void ScrollScreen(int lines_to_scroll)
Definition: curses.c:509
end_of_list
void end_of_list(void)
Definition: global.c:191
t_config::scroll_lines
int scroll_lines
Definition: tinrc.h:144
MOUSE_BUTTON_1
#define MOUSE_BUTTON_1
Definition: tin.h:2109
TRUE
#define TRUE
Definition: bool.h:74
KEYMAP_UP
#define KEYMAP_UP
Definition: tin.h:1066
NOTESLINES
int NOTESLINES
Definition: signal.c:111
NOT_ASSIGNED
@ NOT_ASSIGNED
Definition: keymap.h:149
clear_message
void clear_message(void)
Definition: screen.c:243
KEYMAP_DOWN
#define KEYMAP_DOWN
Definition: tin.h:1067
mail_bug_report
t_bool mail_bug_report(void)
Definition: post.c:3459