summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/apps/embeddedkonsole/konsole.cpp45
1 files changed, 43 insertions, 2 deletions
diff --git a/core/apps/embeddedkonsole/konsole.cpp b/core/apps/embeddedkonsole/konsole.cpp
index eafc12e..084c39d 100644
--- a/core/apps/embeddedkonsole/konsole.cpp
+++ b/core/apps/embeddedkonsole/konsole.cpp
@@ -1,419 +1,460 @@
1 1
2/* ---------------------------------------------------------------------- */ 2/* ---------------------------------------------------------------------- */
3/* */ 3/* */
4/* [main.C] Konsole */ 4/* [main.C] Konsole */
5/* */ 5/* */
6/* ---------------------------------------------------------------------- */ 6/* ---------------------------------------------------------------------- */
7/* */ 7/* */
8/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ 8/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
9/* */ 9/* */
10/* This file is part of Konsole, an X terminal. */ 10/* This file is part of Konsole, an X terminal. */
11/* */ 11/* */
12/* The material contained in here more or less directly orginates from */ 12/* The material contained in here more or less directly orginates from */
13/* kvt, which is copyright (c) 1996 by Matthias Ettrich <ettrich@kde.org> */ 13/* kvt, which is copyright (c) 1996 by Matthias Ettrich <ettrich@kde.org> */
14/* */ 14/* */
15/* ---------------------------------------------------------------------- */ 15/* ---------------------------------------------------------------------- */
16/* */ 16/* */
17/* Ported Konsole to Qt/Embedded */ 17/* Ported Konsole to Qt/Embedded */
18/* */ 18/* */
19/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ 19/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
20/* */ 20/* */
21/* -------------------------------------------------------------------------- */ 21/* -------------------------------------------------------------------------- */
22// enhancements added by L.J. Potter <ljp@llornkcor.com> 22// enhancements added by L.J. Potter <ljp@llornkcor.com>
23// enhancements added by Phillip Kuhn 23// enhancements added by Phillip Kuhn
24 24
25#include <stdlib.h> 25#include <stdlib.h>
26#include <sys/types.h>
27#include <pwd.h>
28#include <unistd.h>
26 29
27#ifdef QT_QWS_OPIE 30#ifdef QT_QWS_OPIE
28#include <opie2/ocolorpopupmenu.h> 31#include <opie2/ocolorpopupmenu.h>
29#endif 32#endif
30 33
31#include <qpe/resource.h> 34#include <qpe/resource.h>
32 35
33#include <qdir.h> 36#include <qdir.h>
34#include <qevent.h> 37#include <qevent.h>
35#include <qdragobject.h> 38#include <qdragobject.h>
36#include <qobjectlist.h> 39#include <qobjectlist.h>
37#include <qtoolbutton.h> 40#include <qtoolbutton.h>
38#include <qtoolbar.h> 41#include <qtoolbar.h>
39#include <qpushbutton.h> 42#include <qpushbutton.h>
40#include <qfontdialog.h> 43#include <qfontdialog.h>
41#include <qglobal.h> 44#include <qglobal.h>
42#include <qpainter.h> 45#include <qpainter.h>
43#include <qmenubar.h> 46#include <qmenubar.h>
44#include <qmessagebox.h> 47#include <qmessagebox.h>
45#include <qaction.h> 48#include <qaction.h>
46#include <qapplication.h> 49#include <qapplication.h>
47#include <qfontmetrics.h> 50#include <qfontmetrics.h>
48#include <qcombobox.h> 51#include <qcombobox.h>
49#include <qevent.h> 52#include <qevent.h>
50#include <qtabwidget.h> 53#include <qtabwidget.h>
51#include <qtabbar.h> 54#include <qtabbar.h>
52#include <qpe/config.h> 55#include <qpe/config.h>
53#include <qstringlist.h> 56#include <qstringlist.h>
54#include <qpalette.h> 57#include <qpalette.h>
55#include <qfontdatabase.h> 58#include <qfontdatabase.h>
56#include <qfile.h> 59#include <qfile.h>
57#include <qspinbox.h> 60#include <qspinbox.h>
58#include <qlayout.h> 61#include <qlayout.h>
59#include <qvbox.h> 62#include <qvbox.h>
60 63
61#include <sys/wait.h> 64#include <sys/wait.h>
62#include <stdio.h> 65#include <stdio.h>
63#include <stdlib.h> 66#include <stdlib.h>
64#include <assert.h> 67#include <assert.h>
65 68
66#include "konsole.h" 69#include "konsole.h"
67#include "keytrans.h" 70#include "keytrans.h"
68#include "commandeditdialog.h" 71#include "commandeditdialog.h"
69 72
70class EKNumTabBar : public QTabBar 73class EKNumTabBar : public QTabBar
71{ 74{
72public: 75public:
73 EKNumTabBar(QWidget *parent = 0, const char *name = 0) : 76 EKNumTabBar(QWidget *parent = 0, const char *name = 0) :
74 QTabBar(parent, name) 77 QTabBar(parent, name)
75 {} 78 {}
76 79
77 // QList<QTab> *getTabList() { return(tabList()); } 80 // QList<QTab> *getTabList() { return(tabList()); }
78 81
79 void numberTabs() 82 void numberTabs()
80 { 83 {
81 // Yes, it really is this messy. QTabWidget needs functions 84 // Yes, it really is this messy. QTabWidget needs functions
82 // that provide acces to tabs in a sequential way. 85 // that provide acces to tabs in a sequential way.
83 int m=INT_MIN; 86 int m=INT_MIN;
84 for (int i=0; i<count(); i++) 87 for (int i=0; i<count(); i++)
85 { 88 {
86 QTab* left=0; 89 QTab* left=0;
87 QListIterator<QTab> it(*tabList()); 90 QListIterator<QTab> it(*tabList());
88 int x=INT_MAX; 91 int x=INT_MAX;
89 for( QTab* t; (t=it.current()); ++it ) 92 for( QTab* t; (t=it.current()); ++it )
90 { 93 {
91 int tx = t->rect().x(); 94 int tx = t->rect().x();
92 if ( tx<x && tx>m ) 95 if ( tx<x && tx>m )
93 { 96 {
94 x = tx; 97 x = tx;
95 left = t; 98 left = t;
96 } 99 }
97 } 100 }
98 if ( left ) 101 if ( left )
99 { 102 {
100 left->setText(QString::number(i+1)); 103 left->setText(QString::number(i+1));
101 m = left->rect().x(); 104 m = left->rect().x();
102 } 105 }
103 } 106 }
104 } 107 }
105 108
106 virtual QSize sizeHint() const 109 virtual QSize sizeHint() const
107 { 110 {
108 if (isHidden()) 111 if (isHidden())
109 { 112 {
110 return(QSize(0,0)); 113 return(QSize(0,0));
111 } 114 }
112 else 115 else
113 { 116 {
114 QSize size = QTabBar::sizeHint(); 117 QSize size = QTabBar::sizeHint();
115 int shrink = 5; 118 int shrink = 5;
116 if (qApp->desktop()->width() > 600 || qApp->desktop()->height() > 600) 119 if (qApp->desktop()->width() > 600 || qApp->desktop()->height() > 600)
117 { 120 {
118 shrink = 10; 121 shrink = 10;
119 } 122 }
120 size.setHeight(size.height() - shrink); 123 size.setHeight(size.height() - shrink);
121 return(size); 124 return(size);
122 } 125 }
123 } 126 }
124 127
125}; 128};
126 129
127class EKNumTabWidget : public QTabWidget 130class EKNumTabWidget : public QTabWidget
128{ 131{
129public: 132public:
130 EKNumTabWidget(QWidget* parent) : QTabWidget(parent) 133 EKNumTabWidget(QWidget* parent) : QTabWidget(parent)
131 { 134 {
132 setTabBar(new EKNumTabBar(parent,"EKTabBar")); 135 setTabBar(new EKNumTabBar(parent,"EKTabBar"));
133 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); 136 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
134 } 137 }
135 138
136 EKNumTabBar *getTabBar() const 139 EKNumTabBar *getTabBar() const
137 { 140 {
138 return ((EKNumTabBar*)tabBar()); 141 return ((EKNumTabBar*)tabBar());
139 } 142 }
140 143
141 144
142 void addTab(QWidget* w) 145 void addTab(QWidget* w)
143 { 146 {
144 QTab* t = new QTab(QString::number(tabBar()->count()+1)); 147 QTab* t = new QTab(QString::number(tabBar()->count()+1));
145 QTabWidget::addTab(w,t); 148 QTabWidget::addTab(w,t);
146 } 149 }
147 150
148 void removeTab(QWidget* w) 151 void removeTab(QWidget* w)
149 { 152 {
150 removePage(w); 153 removePage(w);
151 ((EKNumTabBar*)tabBar())->numberTabs(); 154 ((EKNumTabBar*)tabBar())->numberTabs();
152 } 155 }
153}; 156};
154 157
155// This could be configurable or dynamicly generated from the bash history 158// This could be configurable or dynamicly generated from the bash history
156// file of the user 159// file of the user
157static const char *commonCmds[] = 160static const char *commonCmds[] =
158 { 161 {
159 "ls ", // I left this here, cause it looks better than the first alpha 162 "ls ", // I left this here, cause it looks better than the first alpha
160 "cardctl eject", 163 "cardctl eject",
161 "cat ", 164 "cat ",
162 "cd ", 165 "cd ",
163 "chmod ", 166 "chmod ",
164 "clear", 167 "clear",
165 "cp ", 168 "cp ",
166 "dc ", 169 "dc ",
167 "df ", 170 "df ",
168 "dmesg", 171 "dmesg",
169 "echo ", 172 "echo ",
170 "env", 173 "env",
171 "find ", 174 "find ",
172 "free", 175 "free",
173 "grep ", 176 "grep ",
174 "ifconfig ", 177 "ifconfig ",
175 "ipkg ", 178 "ipkg ",
176 "mkdir ", 179 "mkdir ",
177 "mv ", 180 "mv ",
178 "nc localhost 7776", 181 "nc localhost 7776",
179 "nc localhost 7777", 182 "nc localhost 7777",
180 "netstat ", 183 "netstat ",
181 "nslookup ", 184 "nslookup ",
182 "ping ", 185 "ping ",
183 "ps aux", 186 "ps aux",
184 "pwd ", 187 "pwd ",
185 "qcop QPE/System 'linkChanged(QString)' ''", 188 "qcop QPE/System 'linkChanged(QString)' ''",
186 "qcop QPE/System 'restart()'", 189 "qcop QPE/System 'restart()'",
187 "qcop QPE/System 'quit()'", 190 "qcop QPE/System 'quit()'",
188 "rm ", 191 "rm ",
189 "rmdir ", 192 "rmdir ",
190 "route ", 193 "route ",
191 "set ", 194 "set ",
192 "traceroute", 195 "traceroute",
193 196
194 /* 197 /*
195 "gzip", 198 "gzip",
196 "gunzip", 199 "gunzip",
197 "chgrp", 200 "chgrp",
198 "chown", 201 "chown",
199 "date", 202 "date",
200 "dd", 203 "dd",
201 "df", 204 "df",
202 "dmesg", 205 "dmesg",
203 "fuser", 206 "fuser",
204 "hostname", 207 "hostname",
205 "kill", 208 "kill",
206 "killall", 209 "killall",
207 "ln", 210 "ln",
208 "ping", 211 "ping",
209 "mount", 212 "mount",
210 "more", 213 "more",
211 "sort", 214 "sort",
212 "touch", 215 "touch",
213 "umount", 216 "umount",
214 "mknod", 217 "mknod",
215 "netstat", 218 "netstat",
216 */ 219 */
217 220
218 "exit", 221 "exit",
219 NULL 222 NULL
220 }; 223 };
221 224
222 225
226static void konsoleInit(const char** shell) {
227 if(setuid(getuid()) !=0) qDebug("setuid failed");
228 if(setgid(getgid()) != 0) qDebug("setgid failed"); // drop privileges
229
230
231// QPEApplication::grabKeyboard(); // for CTRL and ALT
232
233 qDebug("keyboard grabbed");
234#ifdef FAKE_CTRL_AND_ALT
235 qDebug("Fake Ctrl and Alt defined");
236 QPEApplication::grabKeyboard(); // for CTRL and ALT
237#endif
238
239 *shell = getenv("SHELL");
240 qWarning("SHell initially is %s", *shell );
241
242 if (shell == NULL || *shell == '\0') {
243 struct passwd *ent = 0;
244 uid_t me = getuid();
245 *shell = "/bin/sh";
246
247 while ( (ent = getpwent()) != 0 ) {
248 if (ent->pw_uid == me) {
249 if (ent->pw_shell != "")
250 *shell = ent->pw_shell;
251 break;
252 }
253 }
254 endpwent();
255 }
256
257 if( putenv((char*)"COLORTERM=") !=0)
258 qDebug("putenv failed"); // to trigger mc's color detection
259}
260
261
223Konsole::Konsole(QWidget* parent, const char* name, WFlags fl) : 262Konsole::Konsole(QWidget* parent, const char* name, WFlags fl) :
224 QMainWindow(parent, name, fl) 263 QMainWindow(parent, name, fl)
225{ 264{
226 QStrList args; 265 QStrList tmp; const char* shell;
227 init("/bin/bash",args); 266
267 konsoleInit( &shell);
268 init(shell,tmp);
228} 269}
229 270
230Konsole::Konsole(const char* name, const char* _pgm, QStrList & _args, int) 271Konsole::Konsole(const char* name, const char* _pgm, QStrList & _args, int)
231 : QMainWindow(0, name) 272 : QMainWindow(0, name)
232{ 273{
233 init(_pgm,_args); 274 init(_pgm,_args);
234} 275}
235 276
236struct HistoryItem 277struct HistoryItem
237{ 278{
238 HistoryItem(int c, const QString &l) 279 HistoryItem(int c, const QString &l)
239 { 280 {
240 count = c; 281 count = c;
241 line = l; 282 line = l;
242 } 283 }
243 int count; 284 int count;
244 QString line; 285 QString line;
245}; 286};
246 287
247class HistoryList : public QList<HistoryItem> 288class HistoryList : public QList<HistoryItem>
248{ 289{
249 virtual int compareItems( QCollection::Item item1, QCollection::Item item2) 290 virtual int compareItems( QCollection::Item item1, QCollection::Item item2)
250 { 291 {
251 int c1 = ((HistoryItem*)item1)->count; 292 int c1 = ((HistoryItem*)item1)->count;
252 int c2 = ((HistoryItem*)item2)->count; 293 int c2 = ((HistoryItem*)item2)->count;
253 if (c1 > c2) 294 if (c1 > c2)
254 return(1); 295 return(1);
255 if (c1 < c2) 296 if (c1 < c2)
256 return(-1); 297 return(-1);
257 return(0); 298 return(0);
258 } 299 }
259}; 300};
260 301
261void Konsole::initCommandList() 302void Konsole::initCommandList()
262{ 303{
263 // qDebug("Konsole::initCommandList"); 304 // qDebug("Konsole::initCommandList");
264 Config cfg( "Konsole" ); 305 Config cfg( "Konsole" );
265 cfg.setGroup("Commands"); 306 cfg.setGroup("Commands");
266 // commonCombo->setInsertionPolicy(QComboBox::AtCurrent); 307 // commonCombo->setInsertionPolicy(QComboBox::AtCurrent);
267 commonCombo->clear(); 308 commonCombo->clear();
268 309
269 if (cfg.readEntry("ShellHistory","TRUE") == "TRUE") 310 if (cfg.readEntry("ShellHistory","TRUE") == "TRUE")
270 { 311 {
271 QString histfilename = QString(getenv("HOME")) + "/.bash_history"; 312 QString histfilename = QString(getenv("HOME")) + "/.bash_history";
272 histfilename = cfg.readEntry("ShellHistoryPath",histfilename); 313 histfilename = cfg.readEntry("ShellHistoryPath",histfilename);
273 QFile histfile(histfilename); 314 QFile histfile(histfilename);
274 // note: compiler barfed on: 315 // note: compiler barfed on:
275 // QFile histfile(QString(getenv("HOME")) + "/.bash_history"); 316 // QFile histfile(QString(getenv("HOME")) + "/.bash_history");
276 if (histfile.open( IO_ReadOnly )) 317 if (histfile.open( IO_ReadOnly ))
277 { 318 {
278 QString line; 319 QString line;
279 uint i; 320 uint i;
280 HistoryList items; 321 HistoryList items;
281 322
282 int lineno = 0; 323 int lineno = 0;
283 while(!histfile.atEnd()) 324 while(!histfile.atEnd())
284 { 325 {
285 if (histfile.readLine(line, 200) < 0) 326 if (histfile.readLine(line, 200) < 0)
286 { 327 {
287 break; 328 break;
288 } 329 }
289 line = line.left(line.length()-1); 330 line = line.left(line.length()-1);
290 lineno++; 331 lineno++;
291 332
292 for(i=0; i<items.count(); i++) 333 for(i=0; i<items.count(); i++)
293 { 334 {
294 if (line == items.at(i)->line) 335 if (line == items.at(i)->line)
295 { 336 {
296 // weight recent commands & repeated commands more 337 // weight recent commands & repeated commands more
297 // by adding up the index of each command 338 // by adding up the index of each command
298 items.at(i)->count += lineno; 339 items.at(i)->count += lineno;
299 break; 340 break;
300 } 341 }
301 } 342 }
302 if (i >= items.count()) 343 if (i >= items.count())
303 { 344 {
304 items.append(new HistoryItem(lineno, line)); 345 items.append(new HistoryItem(lineno, line));
305 } 346 }
306 } 347 }
307 items.sort(); 348 items.sort();
308 int n = items.count(); 349 int n = items.count();
309 if (n > 40) 350 if (n > 40)
310 { 351 {
311 n = 40; 352 n = 40;
312 } 353 }
313 for(int i=0; i<n; i++) 354 for(int i=0; i<n; i++)
314 { 355 {
315 // should insert start of command, but keep whole thing 356 // should insert start of command, but keep whole thing
316 if (items.at(items.count()-i-1)->line.length() < 30) 357 if (items.at(items.count()-i-1)->line.length() < 30)
317 { 358 {
318 commonCombo->insertItem(items.at(items.count()-i-1)->line); 359 commonCombo->insertItem(items.at(items.count()-i-1)->line);
319 } 360 }
320 } 361 }
321 histfile.close(); 362 histfile.close();
322 } 363 }
323 } 364 }
324 if (cfg.readEntry("Commands Set","FALSE") == "FALSE") 365 if (cfg.readEntry("Commands Set","FALSE") == "FALSE")
325 { 366 {
326 for (int i = 0; commonCmds[i] != NULL; i++) 367 for (int i = 0; commonCmds[i] != NULL; i++)
327 { 368 {
328 commonCombo->insertItem(commonCmds[i]); 369 commonCombo->insertItem(commonCmds[i]);
329 } 370 }
330 } 371 }
331 else 372 else
332 { 373 {
333 for (int i = 0; i < 100; i++) 374 for (int i = 0; i < 100; i++)
334 { 375 {
335 if (!(cfg.readEntry( QString::number(i),"")).isEmpty()) 376 if (!(cfg.readEntry( QString::number(i),"")).isEmpty())
336 commonCombo->insertItem(cfg.readEntry( QString::number(i),"")); 377 commonCombo->insertItem(cfg.readEntry( QString::number(i),""));
337 } 378 }
338 } 379 }
339 380
340 381
341} 382}
342 383
343static void sig_handler(int x) 384static void sig_handler(int x)
344{ 385{
345 printf("got signal %d\n",x); 386 printf("got signal %d\n",x);
346} 387}
347 388
348void Konsole::init(const char* _pgm, QStrList & _args) 389void Konsole::init(const char* _pgm, QStrList & _args)
349{ 390{
350 391
351#if 0 392#if 0
352 for(int i=1; i<=31; i++) 393 for(int i=1; i<=31; i++)
353 { 394 {
354 if (i != SIGPIPE && i != SIGPROF && i != SIGSEGV 395 if (i != SIGPIPE && i != SIGPROF && i != SIGSEGV
355 && i != SIGINT && i != SIGILL && i != SIGTERM 396 && i != SIGINT && i != SIGILL && i != SIGTERM
356 && i != SIGBUS) 397 && i != SIGBUS)
357 signal(i,sig_handler); 398 signal(i,sig_handler);
358 } 399 }
359#endif 400#endif
360 signal(SIGSTOP, sig_handler); 401 signal(SIGSTOP, sig_handler);
361 signal(SIGCONT, sig_handler); 402 signal(SIGCONT, sig_handler);
362 signal(SIGTSTP, sig_handler); 403 signal(SIGTSTP, sig_handler);
363 404
364 b_scroll = TRUE; // histon; 405 b_scroll = TRUE; // histon;
365 n_keytab = 0; 406 n_keytab = 0;
366 n_render = 0; 407 n_render = 0;
367 startUp=0; 408 startUp=0;
368 fromMenu = FALSE; 409 fromMenu = FALSE;
369 fullscreen = false; 410 fullscreen = false;
370 411
371 setCaption( tr( "Konsole" ) ); 412 setCaption( tr( "Konsole" ) );
372 setIcon( Resource::loadPixmap( "konsole/Terminal" ) ); 413 setIcon( Resource::loadPixmap( "konsole/Terminal" ) );
373 414
374 Config cfg( "Konsole" ); 415 Config cfg( "Konsole" );
375 cfg.setGroup("Font"); 416 cfg.setGroup("Font");
376 QString tmp; 417 QString tmp;
377 418
378 // initialize the list of allowed fonts /////////////////////////////////// 419 // initialize the list of allowed fonts ///////////////////////////////////
379 420
380 QString cfgFontName = cfg.readEntry("FontName","Lcfont"); 421 QString cfgFontName = cfg.readEntry("FontName","Lcfont");
381 int cfgFontSize = cfg.readNumEntry("FontSize",18); 422 int cfgFontSize = cfg.readNumEntry("FontSize",18);
382 423
383 cfont = -1; 424 cfont = -1;
384 425
385 // this code causes repeated access to all the font files 426 // this code causes repeated access to all the font files
386 // which does slow down startup 427 // which does slow down startup
387 QFontDatabase fontDB; 428 QFontDatabase fontDB;
388 QStringList familyNames; 429 QStringList familyNames;
389 familyNames = fontDB.families( FALSE ); 430 familyNames = fontDB.families( FALSE );
390 QString s; 431 QString s;
391 int fontIndex = 0; 432 int fontIndex = 0;
392 int familyNum = 0; 433 int familyNum = 0;
393 fontList = new QPopupMenu( this ); 434 fontList = new QPopupMenu( this );
394 435
395 for(uint j = 0; j < (uint)familyNames.count(); j++) 436 for(uint j = 0; j < (uint)familyNames.count(); j++)
396 { 437 {
397 s = familyNames[j]; 438 s = familyNames[j];
398 if ( s.contains('-') ) 439 if ( s.contains('-') )
399 { 440 {
400 int i = s.find('-'); 441 int i = s.find('-');
401 s = s.right( s.length() - i - 1 ) + " [" + s.left( i ) + "]"; 442 s = s.right( s.length() - i - 1 ) + " [" + s.left( i ) + "]";
402 } 443 }
403 s[0] = s[0].upper(); 444 s[0] = s[0].upper();
404 445
405 QValueList<int> sizes = fontDB.pointSizes( familyNames[j] ); 446 QValueList<int> sizes = fontDB.pointSizes( familyNames[j] );
406 447
407 printf("family[%d] = %s with %d sizes\n", j, familyNames[j].latin1(), 448 printf("family[%d] = %s with %d sizes\n", j, familyNames[j].latin1(),
408 sizes.count()); 449 sizes.count());
409 450
410 if (sizes.count() > 0) 451 if (sizes.count() > 0)
411 { 452 {
412 QPopupMenu *sizeMenu; 453 QPopupMenu *sizeMenu;
413 QFont f; 454 QFont f;
414 int last_width = -1; 455 int last_width = -1;
415 sizeMenu = NULL; 456 sizeMenu = NULL;
416 457
417 for(uint i = 0; i < (uint)sizes.count() + 4; i++) 458 for(uint i = 0; i < (uint)sizes.count() + 4; i++)
418 { 459 {
419 // printf("family %s size %d ", familyNames[j].latin1(), sizes[i]); 460 // printf("family %s size %d ", familyNames[j].latin1(), sizes[i]);