UltraScan III
us_window_message.cpp
Go to the documentation of this file.
1 #include "us_window_message.h"
2 
3 // A class for sending IPC messages/commands to an external window.
4 // This is primarily meant for SOMO communications with RASMOL.
5 
6 
7 // Platform-specific C function definitions
8 #ifdef Q_WS_X11
9 extern "C" {
10 #include "us_x11_utils.h"
11 }
12 #endif
13 #ifdef Q_WS_MAC
14 extern "C" {
15 #include "us_mac_utils.h"
16 }
17 #endif
18 #ifdef Q_WS_WIN
19 extern "C" {
20 #include "us_win_utils.h"
21 }
22 #endif
23 
24 // Constructor for subclass Interpreter
26  QString fname )
27 {
28  interp_id = ntrpid;
29  interp_name = iname;
30  file_name = fname;
31 }
32 
33 // Constructor that mainly just gets a list of present live interpreters
34 US_WindowMessage::US_WindowMessage( QObject* parent ) : QObject( parent )
35 {
37 }
38 
39 // Function to issue a "winfo interps" command and populate an internal list
40 // of all interpreters.
42 {
43  char nameints[ 512 ];
44  int nintrp = 0;
45 
46  // Get the interpreters' list using platform-dependent methods
47  int nchar = ShowInterpNames( nameints, 511 );
48 
49  if ( nchar > 0 )
50  { // Parse the character array to build a list of interpreter objects
51  nintrp = fill_interps( nchar, nameints, all_interps );
52  }
53 
54  return nintrp;
55 }
56 
57 // Function to issue a "winfo interps" command, populate an internal list
58 // of all interpreters, and return a copy.
59 int US_WindowMessage::findAllInterps( QList< Interpreter >& interps )
60 {
61  int nintrp = findAllInterps(); // Build the internal list of interps
62  interps = all_interps; // Copy the list to the user's list
63  return nintrp;
64 }
65 
66 // Function to generate the internal list of active RasMol interpreters
68 {
69  live_interps.clear();
70  zombie_list .clear();
71 
72  int nintrp = findAllInterps(); // Build the internal list of interps
73 
74  for ( int ii = 0; ii < nintrp; ii++ )
75  { // Loop to generate the "live" list from the "all"
76  Interpreter intrp = all_interps[ ii ];
77 
78  if ( isLive( intrp ) )
79  { // If live, add to the list
80  live_interps << intrp;
81  }
82 
83  else
84  { // Otherwise, add an identifying string to the zombie list
85  zombie_list << QString().sprintf( "%lx : ", intrp.interp_id )
86  + intrp.interp_name;
87  }
88  }
89 
90  return live_interps.size();
91 }
92 
93 // Function to regenerate the list of active RasMol interpreters and
94 // to return a copy of the list
95 int US_WindowMessage::findLiveInterps( QList< Interpreter >& interps )
96 {
97  findLiveInterps(); // Generate internal list of live interps
98 
99  interps = live_interps; // Return a copy
100 
101  return live_interps.size(); // Return with the count
102 }
103 
104 // Function to return any zombie list
105 int US_WindowMessage::zombieList( QStringList& zlist )
106 {
107  int nzomb = zombie_list.size();
108 
109  if ( nzomb > 0 )
110  zlist = zombie_list;
111 
112  return nzomb;
113 }
114 
115 // Function to add a new interpreter, identified by the name of the file
116 // displayed in its window, and return its ID.
117 ulong US_WindowMessage::addInterp( const QString filename )
118 {
119  ulong id = 0;
120 
121  // Save a list of IDs from last active list
122  QList< ulong > ids;
123 
124  for ( int ii = 0; ii < live_interps.size(); ii++ )
125  {
126  ids << live_interps[ ii ].interp_id;
127  }
128 
129  // Update the live interpreters list
130  int nintrp = findLiveInterps( );
131  int newx = -1;
132 
133  // Interpreter in live list to update is the last new one
134  for ( int ii = 0; ii < nintrp; ii++ )
135  {
136  ulong lvid = live_interps[ ii ].interp_id;
137 
138  if ( !ids.contains( lvid ) )
139  { // This is a newly added interpreter, so save its index
140  newx = ii;
141  id = lvid;
142  }
143  }
144 
145  if ( newx >= 0 )
146  { // Update the file name for the newly added interpreter
147  live_interps[ newx ].file_name = filename;
148  }
149 
150  return id;
151 }
152 
153 // Function to return the list of active interpreter IDs.
154 int US_WindowMessage::interpIDs( QList< ulong >& ids )
155 {
156  int nntrp = live_interps.size();
157  ids.clear();
158 
159  for ( int ii = 0; ii < nntrp; ii++ )
160  ids << live_interps[ ii ].interp_id;
161 
162  return nntrp;
163 }
164 
165 // Function to return the list of active interpreter names.
166 int US_WindowMessage::interpNames( QStringList& names )
167 {
168  int nntrp = live_interps.size();
169  names.clear();
170 
171  for ( int ii = 0; ii < nntrp; ii++ )
172  names << live_interps[ ii ].interp_name;
173 
174  return nntrp;
175 }
176 
177 // Function to return a list of active interpreter file names.
178 int US_WindowMessage::interpFiles( QStringList& fnames )
179 {
180  int nntrp = live_interps.size();
181  fnames.clear();
182 
183  for ( int ii = 0; ii < nntrp; ii++ )
184  fnames << live_interps[ ii ].file_name;
185 
186  return nntrp;
187 }
188 
189 // Function to return the interp ID for a given file name.
190 ulong US_WindowMessage::interpId( const QString filename )
191 {
192  ulong id = 0;
193 
194  for ( int ii = 0; ii < live_interps.size(); ii++ )
195  {
196  if ( live_interps[ ii ].file_name == filename )
197  {
198  id = live_interps[ ii ].interp_id;
199  break;
200  }
201  }
202 
203  return id;
204 }
205 
206 // Function to return the interp ID for a given interp name.
208 {
209  ulong id = 0;
210 
211  for ( int ii = 0; ii < live_interps.size(); ii++ )
212  {
213  if ( live_interps[ ii ].interp_name == iname )
214  {
215  id = live_interps[ ii ].interp_id;
216  break;
217  }
218  }
219 
220  return id;
221 }
222 
223 // Function to return the interp name for a given ID.
225 {
226  QString iname = "";
227 
228  for ( int ii = 0; ii < live_interps.size(); ii++ )
229  {
230  if ( live_interps[ ii ].interp_id == id )
231  {
232  iname = live_interps[ ii ].interp_name;
233  break;
234  }
235  }
236 
237  return iname;
238 }
239 
240 // Function to return the interp name for a given file name.
241 QString US_WindowMessage::interpName( const QString filename )
242 {
243  QString iname = "";
244 
245  for ( int ii = 0; ii < live_interps.size(); ii++ )
246  {
247  if ( live_interps[ ii ].file_name == filename )
248  {
249  iname = live_interps[ ii ].interp_name;
250  break;
251  }
252  }
253 
254  return iname;
255 }
256 
257 // Function to return the file name for a given ID.
259 {
260  QString fname = "";
261 
262  for ( int ii = 0; ii < live_interps.size(); ii++ )
263  {
264  if ( live_interps[ ii ].interp_id == id )
265  {
266  fname = live_interps[ ii ].file_name;
267  break;
268  }
269  }
270 
271  return fname;
272 }
273 
274 // Function to return the file name for a given interp name.
275 QString US_WindowMessage::interpFileName( const QString iname )
276 {
277  QString fname = "";
278 
279  for ( int ii = 0; ii < live_interps.size(); ii++ )
280  {
281  if ( live_interps[ ii ].interp_name == iname )
282  {
283  fname = live_interps[ ii ].file_name;
284  break;
285  }
286  }
287 
288  return fname;
289 }
290 
291 // Function to send a message to an interpreter as identified by an ID number.
292 int US_WindowMessage::sendMessage( const ulong id, const QString wmsg )
293 {
294  QString iname = interpName( id );
295  return SendCommand( id, iname.toAscii().data(), wmsg.toAscii().data() );
296 }
297 
298 // Function to send a message to an interpreter as identified by interp name.
299 int US_WindowMessage::sendMessage( const QString iname, const QString wmsg )
300 {
301  ulong id = interpIdByName( iname );
302  return SendCommand( id, iname.toAscii().data(), wmsg.toAscii().data() );
303 }
304 
305 // Function to query an interpreter by interp ID and return the response.
306 QString US_WindowMessage::sendQuery( const ulong id, const QString wmsg )
307 {
308  char resp[ 1024 ];
309  QString iname = interpName( id );
310  SendQuery( id, iname.toAscii().data(), wmsg.toAscii().data(), resp, 1024 );
311  return QString( resp );
312 }
313 
314 // Function to query an interpreter by interp name and return the response.
315 QString US_WindowMessage::sendQuery( const QString iname, const QString wmsg )
316 {
317  char resp[ 1024 ];
318  ulong id = interpIdByName( iname );
319  SendQuery( id, iname.toAscii().data(), wmsg.toAscii().data(), resp, 1024 );
320  return QString( resp );
321 }
322 
323 // Function to determine if an interpreter is live
325 {
326  char ctest[ 64 ] = "echo hello ";
327  char* iname = interp.interp_name.toAscii().data();
328  strcat( ctest, iname );
329 
330  return ( SendCommand( interp.interp_id, iname, ctest ) == 0 );
331 }
332 
333 // Function to return a status/error message from the last interpreter
334 // send action.
336 {
337  return QString( GetLastError() );
338 }
339 
340 // Internal function to parse "winfo interps" results to build a list
341 // of interpreters.
342 int US_WindowMessage::fill_interps( int nchar, char* wiresult,
343  QList< Interpreter >& intrps )
344 {
345  int niknt = 0;
346  intrps.clear();
347 
348  bool ok;
349  int kchar = nchar;
350  char* ptr1 = wiresult;
351 
352  while ( kchar > 0 )
353  {
354  int jchar = (int)strlen( ptr1 );
355 
356  if ( jchar == 0 ) break;
357 
358  QString ires = QString( ptr1 );
359  ulong iid = ires.section( " ", 0, 0 ).toULong( &ok, 16 );
360  QString iname = ires.section( " ", 1, -1 ).simplified();
361  ptr1 += ( ++jchar );
362  kchar -= jchar;
363 
364  intrps << Interpreter( iid, iname, "" );
365  niknt++;
366  }
367 
368  return niknt;
369 }
370