OSDN Git Service

* public snapshot of sid simulator
[pf3gnuchains/pf3gnuchains3x.git] / sid / demos / voice-pager / page-lcd.cxx
1 // page-lcd.cxx - description.  -*- C++ -*-
2
3 // Copyright (C) 1999, 2000 Red Hat.
4 // This file is part of SID and is licensed under the GPL.
5 // See the file COPYING.SID for conditions for redistribution.
6
7 #include "page-lcd.h"
8 #include <stdio.h>
9
10 PagerUI :: PagerUI(lcd_driver& lcd)
11   :lcd_drobj(lcd)
12  {
13    root = new Entry;
14    root->next = root;
15    root->prev = root;
16    root->time_msg = "";
17    root->id = 0;  // invalid id or only valid for root element. 
18
19    total = 0;
20    first_visible = 0;
21    curr_line = 0;
22    NROWS = lcd_drobj.get_numrows();
23    NCOLS = lcd_drobj.get_numcols();
24    // assuming lcd is already initialized by the program during its start.
25    // MAKE SURE ASSUMPTION IS RIGHT
26  }
27
28
29 // Displays message. Arrow is drawn only on the current line.
30 void
31 PagerUI :: draw_line( bool curr, int num, string msg ) 
32 {
33   // write a text string
34   lcd_drobj.send_cmd( lcd_driver::SET_AWRITE );
35
36   if( curr )
37     lcd_drobj.auto_write( 0x80 ); // prints arrow
38
39   else
40     lcd_drobj.auto_write( 0 );  // prints space
41
42   if (num < 10)
43     {
44      lcd_drobj.auto_write(0); // putting a blank.
45      lcd_drobj.auto_write( '0' + num - ' ' );  // prints number
46     }
47
48   else 
49     { // num >= 10
50      char s[3];
51      sprintf (s, "%d", num);
52      string string_rep(s);
53      lcd_drobj.auto_write (string_rep[0] - ' ');        
54      lcd_drobj.auto_write (string_rep[1] - ' ');        
55     }
56     lcd_drobj.auto_write( 0 ); // prints blank/space.
57
58   for( unsigned int i=0; i < msg.size(); i++ ) 
59     lcd_drobj.auto_write( msg[i] - ' ' );
60
61   lcd_drobj.reset_auto( 8 );
62 }
63
64 void
65 PagerUI :: draw_screen() {
66   int i, row;
67   string msg;
68
69   lcd_drobj.mem_set (0, 0, NROWS*NCOLS);  
70   for( row=0; row<NROWS; row++ ) {
71     lcd_drobj.set_word_reg( lcd_driver::SET_ADP, row*NCOLS, 0 );
72                                  // always points at start of line
73
74     i = first_visible + row;
75
76     if( row == (NROWS - 1) ) {
77       if( i < (total - 1) ) { // more than 6 msgs.
78         msg = "more...";
79
80         lcd_drobj.send_cmd( lcd_driver::SET_AWRITE );
81
82         for( unsigned c=0; c < (NCOLS - msg.size()); c++ ) 
83           lcd_drobj.auto_write( 0 );
84
85         for( unsigned c=0; c<msg.size(); c++ ) 
86           lcd_drobj.auto_write( msg[c] - ' ' );
87
88         lcd_drobj.reset_auto( 8 );
89         break;
90       }
91     }
92
93     msg = message( i );
94     if( msg != "" )
95       draw_line( i == curr_line, i + 1, msg );
96     else {
97       if( i < total ) 
98         cerr << "gee - aren't there more lines to draw?" << endl;
99
100       lcd_drobj.send_cmd( lcd_driver::SET_AWRITE );
101
102       for( unsigned c=0; c<NCOLS; c++ ) 
103         lcd_drobj.auto_write( 0 ); // printing blanks.
104
105       lcd_drobj.reset_auto( 8 );
106     }
107   }
108 }
109
110 // Store new message.
111 void
112 PagerUI :: append( int id, string message ) {
113   if( total > MAX_MSGS ) {
114     cerr << " Cannot store more than 9 messages. Contact Rony or Fassi \n";
115     return;
116   }
117
118   Entry *curr = new Entry;
119
120   curr->next = root;
121   curr->prev = root->prev;
122   curr->id = id;
123   curr->time_msg = message;
124
125   root->prev->next = curr;
126   root->prev = curr;
127
128   ++total;
129   select_line( total - 1 );
130 }
131
132 string
133 PagerUI :: remove( int index ) {
134   int i;
135   if ( root->next != root) {
136     Entry* curr = root->next;
137     string msg;
138
139     if ( index >= total )
140       return "";
141
142     for ( i=0; i<index; i++ )
143        curr = curr->next;
144
145     msg = curr->time_msg;
146     curr->prev->next = curr->next;
147     curr->next->prev = curr->prev;
148     delete curr;
149
150     --total;
151     if (total < 0) cerr << " total is less than zero ?? \n";
152       return msg;
153   }
154   else {
155     if (index > 0)
156       cerr << " Root next is root and index > 0 \n";
157     else
158       cout << " Root next is root and index is  0 \n";
159     return "";  
160   }
161 }
162
163 string
164 PagerUI :: message( int index ) {
165   int i;
166   Entry* curr = root->next;
167
168   if( index >= total )
169     return "";
170
171   for( i=0; i<index; i++ )
172     curr = curr->next;
173
174   return curr->time_msg;
175 }
176
177 void
178 PagerUI :: delete_selected() {
179   string msg = remove( curr_line );
180
181   if  (curr_line >= total) {
182     if (total > 0)
183       curr_line = total - 1;
184     else 
185       curr_line = 0;
186   }
187   // need to think about first visible.
188   check_firstvisible();
189 }
190
191 void
192 PagerUI :: select_line( int line ) {
193   curr_line = line;
194   for (int i = first_visible; i < (total - 1); ++i) {
195       if ( (i + (NROWS - 1)) >= (total - 1) )
196         { // There is no "more" on current display
197            first_visible = i;
198            break;
199         }
200     }
201 }
202
203 int
204 PagerUI :: current_id() {
205   int i;
206   Entry* curr = root->next;
207
208   if( total == 0 )
209     return 0; // changed it from -1
210
211   for( i=0; i < curr_line; i++ )
212     curr = curr->next;
213
214   return curr->id;
215 }
216
217 PagerUI :: ~PagerUI() {
218   while( root->next != root )
219     remove( 0 );
220
221   delete root;
222 }
223
224 void 
225 PagerUI :: up() {
226   if( curr_line > 0 ) {
227     --curr_line;
228     check_firstvisible();
229   }
230 }
231
232 void
233 PagerUI :: down() {
234   if( curr_line < (total - 1) ) {
235     ++curr_line;
236     out_ofrange (curr_line);
237   }
238 }
239
240
241 bool PagerUI :: out_ofrange (int curr_pos)
242 {
243   if ( total > NROWS ) {
244     // there are more msgs then lcd rows
245     if ( (first_visible + (NROWS - 1)) < (total -1) ) { 
246       // it means "more" is on display.      
247       int temp = first_visible + (NROWS - 1);
248
249       if (curr_line < temp) 
250         return false;
251
252       else {
253         // Yup I am out of visible range
254         first_visible += (NROWS -2); // or first_visible = temp -1
255         return true;
256       }
257     }
258     else
259         return false;
260   }      
261   else 
262     return false; // Total !> NROWS thus all msgs can be displayed.
263 }     
264
265 void PagerUI::check_firstvisible()
266 {
267    if ( curr_line < first_visible)
268      {
269        first_visible = curr_line - (NROWS -1); 
270                 // Put first visible so that curr_line is last 
271        if (first_visible < 0) first_visible = 0;
272        else if ( (first_visible + (NROWS -1)) < (total -1) )
273          first_visible++; // because more is going to show up.
274      }
275 }