1/*
2 *  translator.c
3 *
4 *  $Id: translatorchooser.c,v 1.7 2007/02/02 11:58:14 source Exp $
5 *
6 *  The iODBC driver manager.
7 *
8 *  Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com>
9 *  All Rights Reserved.
10 *
11 *  This software is released under the terms of either of the following
12 *  licenses:
13 *
14 *      - GNU Library General Public License (see LICENSE.LGPL)
15 *      - The BSD License (see LICENSE.BSD).
16 *
17 *  Note that the only valid version of the LGPL license as far as this
18 *  project is concerned is the original GNU Library General Public License
19 *  Version 2, dated June 1991.
20 *
21 *  While not mandated by the BSD license, any patches you make to the
22 *  iODBC source code may be contributed back into the iODBC project
23 *  at your discretion. Contributions will benefit the Open Source and
24 *  Data Access community as a whole. Submissions may be made at:
25 *
26 *      http://www.iodbc.org
27 *
28 *
29 *  GNU Library Generic Public License Version 2
30 *  ============================================
31 *  This library is free software; you can redistribute it and/or
32 *  modify it under the terms of the GNU Library General Public
33 *  License as published by the Free Software Foundation; only
34 *  Version 2 of the License dated June 1991.
35 *
36 *  This library is distributed in the hope that it will be useful,
37 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
38 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39 *  Library General Public License for more details.
40 *
41 *  You should have received a copy of the GNU Library General Public
42 *  License along with this library; if not, write to the Free
43 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
44 *
45 *
46 *  The BSD License
47 *  ===============
48 *  Redistribution and use in source and binary forms, with or without
49 *  modification, are permitted provided that the following conditions
50 *  are met:
51 *
52 *  1. Redistributions of source code must retain the above copyright
53 *     notice, this list of conditions and the following disclaimer.
54 *  2. Redistributions in binary form must reproduce the above copyright
55 *     notice, this list of conditions and the following disclaimer in
56 *     the documentation and/or other materials provided with the
57 *     distribution.
58 *  3. Neither the name of OpenLink Software Inc. nor the names of its
59 *     contributors may be used to endorse or promote products derived
60 *     from this software without specific prior written permission.
61 *
62 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
63 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
64 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
65 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
66 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
67 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
68 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
69 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
70 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
71 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
72 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 */
74
75
76#include <sys/stat.h>
77#include <unistd.h>
78#include <time.h>
79
80#include "gui.h"
81#include "img.xpm"
82
83
84static void
85translator_list_select (GtkWidget *widget, gint row, gint column,
86    GdkEvent *event, TTRANSLATORCHOOSER *choose_t)
87{
88  LPSTR translator = NULL;
89
90  if (choose_t)
91    {
92      /* Get the directory name */
93      gtk_clist_get_text (GTK_CLIST (choose_t->translatorlist), row, 0,
94	  &translator);
95
96      if (translator && event && event->type == GDK_2BUTTON_PRESS)
97	gtk_signal_emit_by_name (GTK_OBJECT (choose_t->b_finish), "clicked",
98	    choose_t);
99    }
100}
101
102
103static void
104translatorchooser_ok_clicked (GtkWidget *widget,
105    TTRANSLATORCHOOSER *choose_t)
106{
107  char *szTranslator;
108
109  if (choose_t)
110    {
111      if (GTK_CLIST (choose_t->translatorlist)->selection != NULL)
112	{
113	  gtk_clist_get_text (GTK_CLIST (choose_t->translatorlist),
114	      GPOINTER_TO_INT (GTK_CLIST (choose_t->translatorlist)->
115		  selection->data), 0, &szTranslator);
116	  choose_t->translator = dm_SQL_A2W (szTranslator, SQL_NTS);
117	}
118      else
119	choose_t->translator = NULL;
120
121      choose_t->translatorlist = NULL;
122
123      gtk_signal_disconnect_by_func (GTK_OBJECT (choose_t->mainwnd),
124	  GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
125      gtk_main_quit ();
126      gtk_widget_destroy (choose_t->mainwnd);
127    }
128}
129
130
131static void
132translatorchooser_cancel_clicked (GtkWidget *widget,
133    TTRANSLATORCHOOSER *choose_t)
134{
135  if (choose_t)
136    {
137      choose_t->translatorlist = NULL;
138
139      gtk_signal_disconnect_by_func (GTK_OBJECT (choose_t->mainwnd),
140	  GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
141      gtk_main_quit ();
142      gtk_widget_destroy (choose_t->mainwnd);
143    }
144}
145
146
147static gint
148delete_event (GtkWidget *widget,
149    GdkEvent *event, TTRANSLATORCHOOSER *choose_t)
150{
151  translatorchooser_cancel_clicked (widget, choose_t);
152
153  return FALSE;
154}
155
156void
157addtranslators_to_list (GtkWidget *widget, GtkWidget *dlg)
158{
159  char *curr, *buffer = (char *) malloc (sizeof (char) * 65536), *szDriver;
160  char driver[1024], _date[1024], _size[1024];
161  char *data[4];
162  int len, i;
163  BOOL careabout;
164  UWORD confMode = ODBC_USER_DSN;
165  struct stat _stat;
166
167  if (!buffer || !GTK_IS_CLIST (widget))
168    return;
169  gtk_clist_clear (GTK_CLIST (widget));
170
171  /* Get the current config mode */
172  while (confMode != ODBC_SYSTEM_DSN + 1)
173    {
174      /* Get the list of drivers in the user context */
175      SQLSetConfigMode (confMode);
176#ifdef WIN32
177      len =
178	  SQLGetPrivateProfileString ("ODBC 32 bit Translators",
179	  NULL, "", buffer, 65535, "odbcinst.ini");
180#else
181      len =
182	  SQLGetPrivateProfileString ("ODBC Translators",
183	  NULL, "", buffer, 65535, "odbcinst.ini");
184#endif
185      if (len)
186	goto process;
187
188      goto end;
189
190    process:
191      for (curr = buffer; *curr; curr += (STRLEN (curr) + 1))
192	{
193	  /* Shadowing system odbcinst.ini */
194	  for (i = 0, careabout = TRUE; i < GTK_CLIST (widget)->rows; i++)
195	    {
196	      gtk_clist_get_text (GTK_CLIST (widget), i, 0, &szDriver);
197	      if (!strcmp (szDriver, curr))
198		{
199		  careabout = FALSE;
200		  break;
201		}
202	    }
203
204	  if (!careabout)
205	    continue;
206
207	  SQLSetConfigMode (confMode);
208#ifdef WIN32
209	  SQLGetPrivateProfileString ("ODBC 32 bit Translators",
210	      curr, "", driver, sizeof (driver), "odbcinst.ini");
211#else
212	  SQLGetPrivateProfileString ("ODBC Translators",
213	      curr, "", driver, sizeof (driver), "odbcinst.ini");
214#endif
215
216	  /* Check if the driver is installed */
217	  if (strcasecmp (driver, "Installed"))
218	    goto end;
219
220	  /* Get the driver library name */
221	  SQLSetConfigMode (confMode);
222	  if (!SQLGetPrivateProfileString (curr,
223		  "Translator", "", driver, sizeof (driver), "odbcinst.ini"))
224	    {
225	      SQLSetConfigMode (confMode);
226	      SQLGetPrivateProfileString ("Default",
227		  "Translator", "", driver, sizeof (driver), "odbcinst.ini");
228	    }
229
230	  if (STRLEN (curr) && STRLEN (driver))
231	    {
232	      data[0] = curr;
233	      data[1] = driver;
234
235	      /* Get some information about the driver */
236	      if (!stat (driver, &_stat))
237		{
238		  sprintf (_size, "%lu Kb",
239		      (unsigned long) _stat.st_size / 1024L);
240		  sprintf (_date, "%s", ctime (&_stat.st_mtime));
241		  data[2] = _date;
242		  data[3] = _size;
243		  gtk_clist_append (GTK_CLIST (widget), data);
244		}
245	    }
246	}
247
248    end:
249      if (confMode == ODBC_USER_DSN)
250	confMode = ODBC_SYSTEM_DSN;
251      else
252	confMode = ODBC_SYSTEM_DSN + 1;
253    }
254
255  if (GTK_CLIST (widget)->rows > 0)
256    {
257      gtk_clist_columns_autosize (GTK_CLIST (widget));
258      gtk_clist_sort (GTK_CLIST (widget));
259    }
260
261  /* Make the clean up */
262  free (buffer);
263}
264
265
266void
267create_translatorchooser (HWND hwnd, TTRANSLATORCHOOSER *choose_t)
268{
269  GtkWidget *translatorchooser, *dialog_vbox1, *fixed1, *l_diz,
270      *scrolledwindow1;
271  GtkWidget *clist1, *l_name, *l_file, *l_date, *l_size, *dialog_action_area1;
272  GtkWidget *hbuttonbox1, *b_finish, *b_cancel, *pixmap1;
273  guint b_finish_key, b_cancel_key;
274  GdkPixmap *pixmap;
275  GdkBitmap *mask;
276  GtkStyle *style;
277  GtkAccelGroup *accel_group;
278
279  if (hwnd == NULL || !GTK_IS_WIDGET (hwnd))
280    return;
281
282  accel_group = gtk_accel_group_new ();
283
284  translatorchooser = gtk_dialog_new ();
285  gtk_object_set_data (GTK_OBJECT (translatorchooser), "translatorchooser",
286      translatorchooser);
287  gtk_window_set_title (GTK_WINDOW (translatorchooser),
288      "Choose a Translator");
289  gtk_window_set_position (GTK_WINDOW (translatorchooser),
290      GTK_WIN_POS_CENTER);
291  gtk_window_set_modal (GTK_WINDOW (translatorchooser), TRUE);
292  gtk_window_set_policy (GTK_WINDOW (translatorchooser), FALSE, FALSE, FALSE);
293
294#if GTK_CHECK_VERSION(2,0,0)
295  gtk_widget_show (translatorchooser);
296#endif
297
298  dialog_vbox1 = GTK_DIALOG (translatorchooser)->vbox;
299  gtk_object_set_data (GTK_OBJECT (translatorchooser), "dialog_vbox1",
300      dialog_vbox1);
301  gtk_widget_show (dialog_vbox1);
302
303  fixed1 = gtk_fixed_new ();
304  gtk_widget_ref (fixed1);
305  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "fixed1", fixed1,
306      (GtkDestroyNotify) gtk_widget_unref);
307  gtk_widget_show (fixed1);
308  gtk_box_pack_start (GTK_BOX (dialog_vbox1), fixed1, TRUE, TRUE, 0);
309  gtk_container_set_border_width (GTK_CONTAINER (fixed1), 6);
310
311  l_diz = gtk_label_new ("Select which ODBC Translator you want to use.");
312  gtk_widget_ref (l_diz);
313  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "l_diz", l_diz,
314      (GtkDestroyNotify) gtk_widget_unref);
315  gtk_widget_show (l_diz);
316  gtk_fixed_put (GTK_FIXED (fixed1), l_diz, 168, 16);
317  gtk_widget_set_uposition (l_diz, 168, 16);
318  gtk_widget_set_usize (l_diz, 325, 16);
319  gtk_label_set_justify (GTK_LABEL (l_diz), GTK_JUSTIFY_LEFT);
320
321  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
322  gtk_widget_ref (scrolledwindow1);
323  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "scrolledwindow1",
324      scrolledwindow1, (GtkDestroyNotify) gtk_widget_unref);
325  gtk_widget_show (scrolledwindow1);
326  gtk_fixed_put (GTK_FIXED (fixed1), scrolledwindow1, 168, 32);
327  gtk_widget_set_uposition (scrolledwindow1, 168, 32);
328  gtk_widget_set_usize (scrolledwindow1, 320, 248);
329
330  clist1 = gtk_clist_new (4);
331  gtk_widget_ref (clist1);
332  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "clist1", clist1,
333      (GtkDestroyNotify) gtk_widget_unref);
334  gtk_widget_show (clist1);
335  gtk_container_add (GTK_CONTAINER (scrolledwindow1), clist1);
336  gtk_clist_set_column_width (GTK_CLIST (clist1), 0, 165);
337  gtk_clist_set_column_width (GTK_CLIST (clist1), 1, 118);
338  gtk_clist_set_column_width (GTK_CLIST (clist1), 2, 80);
339  gtk_clist_set_column_width (GTK_CLIST (clist1), 3, 80);
340  gtk_clist_column_titles_show (GTK_CLIST (clist1));
341
342  l_name = gtk_label_new (szDriverColumnNames[0]);
343  gtk_widget_ref (l_name);
344  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "l_name", l_name,
345      (GtkDestroyNotify) gtk_widget_unref);
346  gtk_widget_show (l_name);
347  gtk_clist_set_column_widget (GTK_CLIST (clist1), 0, l_name);
348
349  l_file = gtk_label_new (szDriverColumnNames[1]);
350  gtk_widget_ref (l_file);
351  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "l_file", l_file,
352      (GtkDestroyNotify) gtk_widget_unref);
353  gtk_widget_show (l_file);
354  gtk_clist_set_column_widget (GTK_CLIST (clist1), 1, l_file);
355
356  l_date = gtk_label_new (szDriverColumnNames[2]);
357  gtk_widget_ref (l_date);
358  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "l_date", l_date,
359      (GtkDestroyNotify) gtk_widget_unref);
360  gtk_widget_show (l_date);
361  gtk_clist_set_column_widget (GTK_CLIST (clist1), 2, l_date);
362
363  l_size = gtk_label_new (szDriverColumnNames[3]);
364  gtk_widget_ref (l_size);
365  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "l_size", l_size,
366      (GtkDestroyNotify) gtk_widget_unref);
367  gtk_widget_show (l_size);
368  gtk_clist_set_column_widget (GTK_CLIST (clist1), 3, l_size);
369
370#if GTK_CHECK_VERSION(2,0,0)
371  style = gtk_widget_get_style (translatorchooser);
372  pixmap =
373      gdk_pixmap_create_from_xpm_d (translatorchooser->window, &mask,
374      &style->bg[GTK_STATE_NORMAL], (gchar **) img_xpm);
375#else
376  style = gtk_widget_get_style (GTK_WIDGET (hwnd));
377  pixmap =
378      gdk_pixmap_create_from_xpm_d (GTK_WIDGET (hwnd)->window, &mask,
379      &style->bg[GTK_STATE_NORMAL], (gchar **) img_xpm);
380#endif
381
382  pixmap1 = gtk_pixmap_new (pixmap, mask);
383  gtk_widget_ref (pixmap1);
384  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "pixmap1",
385      pixmap1, (GtkDestroyNotify) gtk_widget_unref);
386  gtk_widget_show (pixmap1);
387  gtk_fixed_put (GTK_FIXED (fixed1), pixmap1, 16, 16);
388  gtk_widget_set_uposition (pixmap1, 16, 16);
389  gtk_widget_set_usize (pixmap1, 136, 264);
390
391  dialog_action_area1 = GTK_DIALOG (translatorchooser)->action_area;
392  gtk_object_set_data (GTK_OBJECT (translatorchooser), "dialog_action_area1",
393      dialog_action_area1);
394  gtk_widget_show (dialog_action_area1);
395  gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area1), 5);
396
397  hbuttonbox1 = gtk_hbutton_box_new ();
398  gtk_widget_ref (hbuttonbox1);
399  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "hbuttonbox1",
400      hbuttonbox1, (GtkDestroyNotify) gtk_widget_unref);
401  gtk_widget_show (hbuttonbox1);
402  gtk_box_pack_start (GTK_BOX (dialog_action_area1), hbuttonbox1, TRUE, TRUE,
403      0);
404  gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_END);
405  gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox1), 10);
406
407  b_finish = gtk_button_new_with_label ("");
408  b_finish_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (b_finish)->child),
409      "_Finish");
410  gtk_widget_add_accelerator (b_finish, "clicked", accel_group,
411      b_finish_key, GDK_MOD1_MASK, 0);
412  gtk_widget_ref (b_finish);
413  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "b_finish",
414      b_finish, (GtkDestroyNotify) gtk_widget_unref);
415  gtk_widget_show (b_finish);
416  gtk_container_add (GTK_CONTAINER (hbuttonbox1), b_finish);
417  GTK_WIDGET_SET_FLAGS (b_finish, GTK_CAN_DEFAULT);
418  gtk_widget_add_accelerator (b_finish, "clicked", accel_group,
419      'F', GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);
420
421  b_cancel = gtk_button_new_with_label ("");
422  b_cancel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (b_cancel)->child),
423      "_Cancel");
424  gtk_widget_add_accelerator (b_cancel, "clicked", accel_group,
425      b_cancel_key, GDK_MOD1_MASK, 0);
426  gtk_widget_ref (b_cancel);
427  gtk_object_set_data_full (GTK_OBJECT (translatorchooser), "b_cancel",
428      b_cancel, (GtkDestroyNotify) gtk_widget_unref);
429  gtk_widget_show (b_cancel);
430  gtk_container_add (GTK_CONTAINER (hbuttonbox1), b_cancel);
431  GTK_WIDGET_SET_FLAGS (b_cancel, GTK_CAN_DEFAULT);
432  gtk_widget_add_accelerator (b_cancel, "clicked", accel_group,
433      'C', GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);
434
435  /* Ok button events */
436  gtk_signal_connect (GTK_OBJECT (b_finish), "clicked",
437      GTK_SIGNAL_FUNC (translatorchooser_ok_clicked), choose_t);
438  /* Cancel button events */
439  gtk_signal_connect (GTK_OBJECT (b_cancel), "clicked",
440      GTK_SIGNAL_FUNC (translatorchooser_cancel_clicked), choose_t);
441  /* Close window button events */
442  gtk_signal_connect (GTK_OBJECT (translatorchooser), "delete_event",
443      GTK_SIGNAL_FUNC (delete_event), choose_t);
444  gtk_signal_connect (GTK_OBJECT (translatorchooser), "destroy",
445      GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
446  /* Translator list events */
447  gtk_signal_connect (GTK_OBJECT (clist1), "select_row",
448      GTK_SIGNAL_FUNC (translator_list_select), choose_t);
449
450  gtk_window_add_accel_group (GTK_WINDOW (translatorchooser), accel_group);
451
452  addtranslators_to_list (clist1, translatorchooser);
453
454  choose_t->translatorlist = clist1;
455  choose_t->translator = NULL;
456  choose_t->mainwnd = translatorchooser;
457  choose_t->b_finish = b_finish;
458
459  gtk_widget_show_all (translatorchooser);
460  gtk_main ();
461}
462