/* コンパイル: [GTK+パスは環境に合わせて設定] set GTK=C:\gtk+2.24.10_win32 [gccの場合] g++ -o rc2fbgtk rc2fbgtk.cpp -I"%GTK%/include\gtk-2.0" -I"%GTK%/include\glib-2.0" -I"%GTK%/lib\glib-2.0\include" -I"%GTK%/include\cairo" -I"%GTK%/include\pango-1.0" -I"%GTK%/lib\gtk-2.0\include" -I"%GTK%/include\gdk-pixbuf-2.0" -I"%GTK%/include\atk-1.0" -L"%GTK%/lib" -lgdk-win32-2.0 -lgtk-win32-2.0 -lglib-2.0 -lgobject-2.0 -lcairo -static [msvcの場合] cl -Fe"rc2fbgtk" rc2fbgtk.cpp -I"%GTK%/include\gtk-2.0" -I"%GTK%/include\glib-2.0" -I"%GTK%/lib\glib-2.0\include" -I"%GTK%/include\cairo" -I"%GTK%/include\pango-1.0" -I"%GTK%/lib\gtk-2.0\include" -I"%GTK%/include\gdk-pixbuf-2.0" -I"%GTK%/include\atk-1.0" user32.lib gdi32.lib -link -libpath:"%GTK%\lib" gdk-win32-2.0.lib gtk-win32-2.0.lib glib-2.0.lib gobject-2.0.lib cairo.lib 使用例:※実行時はGTKのbinディレクトリにパスを通しておく必要があります。 rc2fbgtk test.rc > generate.bas fbc generate.bas -p %GTK%\lib generate */ //#if defined(_MSC_VER) && defined(_WIN32) #include //#endif #include #include #include #include using namespace std; /* * 小文字にする。入力文字列を直接変更する */ char *strlowcase(char *s) { while (*s) { *s = tolower(*s); s++; } return s; } /* * 文字列の置き換えを行う。 * dst : 出力文字列 src : 入力文字列 */ char *strreplace(char *dst, const char *src, const char *from, const char *to) { int l1 = strlen(from); int l2 = strlen(to); char *r = dst; const char *s = src; *dst = 0; const char *p; while ((p = strstr(s, from)) != NULL) { if (p > s) strncpy(r, s, p - s); r[p-s] = 0; r += p - s; s = p + l1; strcpy(r, to); r += l2; } strcpy(r, s); return dst; } char *ltrim(char *s) { char *t = s; char *u = s; while (*t == ' ' || *t == '\t') t++; while (*t) { *u++ = *t++; } *u = 0; return s; } //TODO:切り替えが中途半端。GDI32使うならGTKは必要ないが…… #if defined(_MSC_VER) && defined(_WIN32) /* *簡単にフォントを生成 */ HFONT SetMyFont(HDC hdc, LPCTSTR face, int h, int angle = 0) { HFONT hFont; hFont = CreateFont(h, //フォント高さ 0, //文字幅 angle, //テキストの角度 0, //ベースラインとx軸との角度 FW_REGULAR, //フォントの重さ(太さ) FALSE, //イタリック体 FALSE, //アンダーライン FALSE, //打ち消し線 SHIFTJIS_CHARSET, //文字セット OUT_DEFAULT_PRECIS, //出力精度 CLIP_DEFAULT_PRECIS,//クリッピング精度 PROOF_QUALITY, //出力品質 FIXED_PITCH | FF_MODERN,//ピッチとファミリー face); //書体名 return hFont; } /* * デスクトップのフォントの縦横サイズを取得する * リソースからの座標・サイズの換算に使用する */ SIZE getUnitSize(int h, char* face) { HWND hdtp = GetDesktopWindow(); HDC dc = GetDC(hdtp); TEXTMETRIC txm; SIZE ret; int dpiY = GetDeviceCaps(dc, LOGPIXELSY); //printf("'dpiY=%d\n", dpiY); h = (h * dpiY / 36 + 1) / 2; HFONT hf = SetMyFont(dc, face, h);//Point To Pixels HGDIOBJ obj = SelectObject(dc, hf); //リソース単位の場合はこうする GetTextExtentPoint32(dc, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &ret); //printf("'cx=%d cy=%d\n", ret.cx,ret.cy); GetTextMetrics(dc, &txm); SelectObject(dc, obj); DeleteObject(hf); ReleaseDC(hdtp, dc); ret.cx = (ret.cx / 26 + 1) / 2; ret.cy = txm.tmHeight; //printf("'cx=%d cy=%d\n", ret.cx,ret.cy); return ret; } #else //TODO:……GTKのみにしてWindows.hを外すのはコントロールのクラス名の関係で出来なかった。 /* typedef struct size_win { int cx, xy; } SIZE; */ SIZE getUnitSize(int fontsize, char* fontfamily) { cairo_t *cr; cairo_surface_t *surface; GdkScreen *screen = gdk_screen_get_default(); float dpi = gdk_screen_get_resolution(screen); double size; SIZE ret; cairo_font_extents_t extents; cairo_text_extents_t text_extents; surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 200, 200); cr = cairo_create(surface); cairo_select_font_face(cr, fontfamily, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); if (dpi < 0) dpi = 96.0; size = fontsize * (dpi/72.0); cairo_set_font_size(cr, size); cairo_font_extents(cr, &extents); cairo_text_extents(cr, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", &text_extents); ret.cx = (text_extents.width / 26 + 1) / 2; ret.cy = extents.height; //*descent = extents.descent; cairo_destroy(cr); cairo_surface_destroy(surface); return ret; } #endif char buf[4096]; /* * スタイル値の文字列をBASIC用にC変換 */ char* getstyle(char *wrk, char *p) { ltrim(p); if (*p == '0' && *(p+1) == 'x') { strcpy(wrk, "&H"); strcat(wrk, p+2); } else if (strstr(p, "WS_") != NULL || strstr(p, "|") != NULL) { strreplace(buf, p, "|", "Or"); strreplace(wrk, buf, "NOT ", "0 * "); } else { strcpy(wrk, p); } return wrk; } /* * 改行をカット */ char *strchomp(char *s) { char *p = strchr(s, '\n'); if (p) *p = 0;//chomp return s; } //識別子文字か判別 int isNumAlpUnsc(char c) { return (c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '_'); } //単語単位でサーチ char *srchWord(char *row, const char *word) { int ln = strlen(word); char *p = strstr(row, word); if (p) { while (p && (p > row && isNumAlpUnsc(*(p-1)) || isNumAlpUnsc(*(p+ln)))) { p = strstr(p+ln, word); } } return p; } int chknumsytle(const char *sty, unsigned int flag) { if (sty && *sty) { if (*sty == '0' && *(sty+1) == 'x') { int f = 0; sscanf(sty + 2, "%x", &f); return (f & flag) == flag; } } return 0; } /* * シグナルコールバックを生成 */ void procgen(const char *cnm, const char *enm, string &decl, string &procs, const char *codes = NULL) { sprintf(buf, "Declare Sub %s_%s Cdecl (ByVal widget As GtkWidget Ptr, gdata As gpointer)\n", cnm, enm); decl += buf; sprintf(buf, "Sub %s_%s Cdecl (ByVal widget As GtkWidget Ptr, ByVal gdata As gpointer)\n", cnm, enm); procs += buf; if (codes == NULL) { procs += "\t'Please write your codes here.\n"; } else { procs += codes; } procs += "End Sub\n\n"; } /* * コントロール汎用整形プロシージャ * patten 0 ボタン等 1 エディット等 2 "CONTROL" * decl 変数宣言を出力 * impl 初期化等のコードを出力 */ int m_radios = 0; void control(int pattern, char *p, const char *cls, const char *defstyle, char*dnm, SIZE *unit, string &decl, string &impl, string &dclproc, string &procs) { int left = 0, top = 0, width = 0, height = 0; char buf[256], wrk3[256], wrk4[160], cnm[64], cln[64]; ltrim(p); const char *txt; char *id, *sty; if (pattern == 0) { txt = "\"\""; id = strtok(p, ","); } else { txt = strtok(p, ","); id = strtok(NULL, ","); } ltrim(id); if (pattern == 2) { char *s = strtok(NULL, ","); ltrim(s); strcpy(cln, s); sty = strtok(NULL, ","); } else { strcpy(cln, "\""); strcat(cln, cls); strcat(cln, "\""); } char *px = strtok(NULL, ","); ltrim(px); sscanf(px, "%d", &left); px = strtok(NULL, ","); ltrim(px); sscanf(px, "%d", &top); px = strtok(NULL, ","); ltrim(px); sscanf(px, "%d", &width); px = strtok(NULL, ","); ltrim(px); sscanf(px, "%d", &height); if (pattern != 2) { sty = strtok(NULL, ","); } ltrim(sty); getstyle(wrk3, sty); char *exsty = strtok(NULL, "\n");//残り if (exsty) { ltrim(exsty); getstyle(wrk4, exsty); } else { strcpy(wrk4, "0"); } strcpy(cnm, id); if (!strncmp(cnm, "IDC_", 4)) { strcpy(cnm, id + 4); strlowcase(cnm); } if (!strcmp(cnm, "IDOK")) { strcpy(cnm, "btnOK"); } else if (!strcmp(cnm, "IDCANCEL")) { strcpy(cnm, "btnCancel"); } sprintf(buf, "Dim Shared %s As GtkWidget Ptr\n", cnm); decl += buf; strcat(wrk3, " Or "); strcat(wrk3, defstyle); //コントロールからウィジットへ if (!strcmp(cln,"WC_BUTTON") || !strcmp(cln,"\"button\"")) { //トグルのひな形コード const char *tggled = "\tIf GTK_TOGGLE_BUTTON(widget)->active Then\n" "\t\t' button is raised.\n" "\tElse\n" "\t\t' button is sunken.\n" "\tEnd If\n"; //ボタン if (strstr(wrk3, "BS_PUSHBUTTON")||strstr(wrk3, "BS_DEFPUSHBUTTON")|| chknumsytle(wrk3, BS_PUSHBUTTON) || chknumsytle(wrk3, BS_DEFPUSHBUTTON)) { sprintf(buf, "%s = gtk_button_new_with_label(%s)\n", cnm, txt); impl += buf; sprintf(buf, "g_signal_connect(G_OBJECT(%s), \"clicked\", G_CALLBACK(@%s_clicked), %s)\n", cnm, cnm, dnm); impl += buf; procgen(cnm, "clicked", dclproc, procs); } else if (strstr(wrk3, "BS_AUTOCHECKBOX")||strstr(wrk3, "BS_CHECKBOX")|| chknumsytle(wrk3, BS_AUTOCHECKBOX) || chknumsytle(wrk3, BS_CHECKBOX)) { if (strstr(wrk3, "BS_PUSHLIKE") || chknumsytle(wrk3, BS_PUSHLIKE)) { //トグルボタン sprintf(buf, "%s = gtk_toggle_button_new_with_label(%s)\n", cnm, txt); impl += buf; sprintf(buf, "g_signal_connect(G_OBJECT(%s), \"toggled\", G_CALLBACK(@%s_toggled), %s)\n", cnm, cnm, dnm); impl += buf; procgen(cnm, "toggled", dclproc, procs, tggled); } else { //チェックボタン sprintf(buf, "%s = gtk_check_button_new_with_label(%s)\n", cnm, txt); impl += buf; sprintf(buf, "g_signal_connect(G_OBJECT(%s), \"toggled\", G_CALLBACK(@%s_toggled), %s)\n", cnm, cnm, dnm); impl += buf; procgen(cnm, "toggled", dclproc, procs, tggled); } } else if (strstr(wrk3, "BS_AUTORADIOBUTTON")||strstr(wrk3, "BS_RADIOBUTTON")|| chknumsytle(wrk3, BS_AUTORADIOBUTTON) || chknumsytle(wrk3, BS_RADIOBUTTON)) { //ラジオボタン if (m_radios == 0) { sprintf(buf, "%s = gtk_radio_button_new_with_label(NULL, %s)\n", cnm, txt); impl += buf; sprintf(buf, "Dim group1 As GSList Ptr = gtk_radio_button_group (GTK_RADIO_BUTTON (%s))\n", cnm); } else { sprintf(buf, "%s = gtk_radio_button_new_with_label(group1, %s)\n", cnm, txt); } m_radios++; impl += buf; sprintf(buf, "g_signal_connect(G_OBJECT(%s), \"toggled\", G_CALLBACK(@%s_toggled), %s)\n", cnm, cnm, dnm); impl += buf; procgen(cnm, "toggled", dclproc, procs, tggled); } //フォントセット(子ウィジット) sprintf(buf,"child_set_font(%s, font_desc)\n", cnm); impl += buf; } else if ((!strcmp(cln,"WC_STATIC") || !strcmp(cln,"\"static\"")) && !strstr(wrk3, "RECT") && !strstr(wrk3, "FRAME")) { sprintf(buf, "%s = gtk_label_new(%s)\n", cnm, txt); impl += buf; //フォントセット(直) sprintf(buf,"gtk_widget_modify_font(GTK_WIDGET(%s), font_desc)\n", cnm); impl += buf; } sprintf(buf, "gtk_widget_set_size_request(%s, %d, %d)\n", cnm, width * unit->cx / 4, height * unit->cy / 8); impl += buf; sprintf(buf, "gtk_fixed_put(GTK_FIXED(fixed), %s, %d, %d)\n", cnm, left * unit->cx / 4, top * unit->cy / 8); impl += buf; } /* * メニューリソーススクリプト変換処理(再帰してます) */ void procmenu(char *p, char *mnm, string &decl, string &impl, string &dclproc, string &procs, FILE *f, int dep = 0) { char row[256]; char mn[64]; int i = 10, j = 1; if (dep > 0) { sprintf(mn, "%s%d", mnm, dep); } else { strcpy(mn, mnm); } sprintf(buf, "Dim Shared %s As GtkWidget Ptr\n", mn); decl += buf; if (dep == 0) { sprintf(buf, "%s = gtk_menu_bar_new()\n", mn); } else { sprintf(buf, "%s = gtk_menu_new()\n", mn); } impl += buf; if (fgets(row, sizeof(row), f)) { if (srchWord(row, "BEGIN") != NULL || strchr(row, '{') != NULL) { while(fgets(row, sizeof(row), f)) { strchomp(row); if (srchWord(row, "MENUITEM SEPARATOR") != NULL) { sprintf(buf, "gtk_container_add(GTK_CONTAINER(%s), gtk_menu_item_new())\n", mn); impl += buf; } else if ((p = srchWord(row, "MENUITEM")) != NULL) { p += 9; char *txt = strtok(p, ","); ltrim(txt); char *id = strtok(NULL, ","); ltrim(id); char *mf = strtok(NULL, ","); ltrim(mf); if (!strcmp(mf, "MFT_SEPARATOR")) { sprintf(buf, "gtk_container_add(GTK_CONTAINER(%s), gtk_menu_item_new())\n", mn); impl += buf; } else { if (strstr(id, "IDM_")) { id += 3; *id = 'm'; strlowcase(id+2); } sprintf(buf, "Dim Shared %s As GtkWidget Ptr\n", id); decl += buf; sprintf(buf, "%s = gtk_menu_item_new_with_mnemonic(%s)\n", id, txt); impl += buf; sprintf(buf, "gtk_container_add(GTK_CONTAINER(%s), %s)\n", mn, id); impl += buf; sprintf(buf, "g_signal_connect(G_OBJECT(%s), \"activate\", G_CALLBACK(@%s_activate), NULL)\n", id, id); impl += buf; procgen(id, "activate", dclproc, procs); } } else if ((p = srchWord(row, "POPUP")) != NULL) { p += 5; char *txt = strtok(p, ","); char t[64]; strcpy(t,txt); ltrim(t); int k = dep + i; sprintf(buf, "Dim Shared item%d As GtkWidget Ptr\n", k); decl += buf; procmenu(p, mnm, decl, impl, dclproc, procs, f, dep+i); sprintf(buf, "item%d = gtk_menu_item_new_with_mnemonic(%s)\n", k, t); impl += buf; sprintf(buf, "gtk_container_add(GTK_CONTAINER(%s), item%d)\n", mn, k); impl += buf; sprintf(buf, "gtk_menu_item_set_submenu(GTK_MENU_ITEM(item%d), %s%d)\n", k, mnm, k); impl += buf; i++; } else if (srchWord(row, "END") != NULL || strchr(row, '}') != NULL) { break; } } } } } /* * メイン関数 * ・リファクタリングが十分でなく、読めないコード * ・ダイアログリソースが一つだけ存在するRCでないと正常動作しない */ int main(int argc, char *argv[]) { char row[256]; FILE *f = fopen(argv[1], "rt"); SIZE unit = {0,0}; //int ncw = GetSystemMetrics(SM_CXFRAME) * 2; //int nch = GetSystemMetrics(SM_CYFRAME) * 2 + GetSystemMetrics(SM_CYSIZE); //int cym = GetSystemMetrics(SM_CYMENU); int ncm = 0; string decl; string impl; string menu; string dclproc; string procs; int dlg = 0; char cap[128]; char fnt[64], did[64], dnm[64], cnm[64], mnm[64]; char wrk[256],wrk2[160],wrk3[256],wrk4[160]; int style, exstyle; char *p; if (!f) { printf("ファイルが開けません\n"); return -1; } gtk_init(NULL,NULL); while (fgets(row, sizeof(row), f)) { strchomp(row); if (*row == '#') continue; if ((p = srchWord(row, "DIALOGEX")) != NULL || (p = srchWord(row, "DIALOG")) != NULL) { decl += "' declare dialog\n"; impl += "' dialog\n"; int x, y, h, w, fh; char *str_style = wrk, *str_exstyle = wrk2; strcpy(wrk, "0"); strcpy(wrk2, "0"); style = 0; exstyle = 0; *(p-1) = 0; strcpy(did, row); p += 6; if (*p == 'E') p += 2; sscanf(p, "%d,%d,%d,%d",&x,&y,&w,&h); strcpy(mnm, "NULL"); while(fgets(row, sizeof(row),f)) { strchomp(row); if (*row == 0) break; if ((p = srchWord(row, "STYLE")) != NULL) { str_style = getstyle(wrk, p+5); } else if ((p = srchWord(row, "CAPTION")) != NULL) { strcpy(cap, p+7); ltrim(cap); } else if ((p = srchWord(row, "FONT")) != NULL) { p = strtok(p+5, ","); sscanf(p, "%d", &fh); p = strtok(NULL, ","); ltrim(p); if (*p == '"') p++; strcpy(fnt, p); p = strchr(fnt,'"'); if (p) *p = 0; } else if ((p = srchWord(row, "MENU")) != NULL) { p += 4; ltrim(p); strcpy(mnm, p); if (!strncmp(mnm, "IDR_", 4)) { strcpy(mnm, p + 4); strlowcase(mnm); } ncm = -1;//メニューあり } else if ((p = srchWord(row, "EXSTYLE")) != NULL) { str_exstyle = getstyle(wrk2, p+7); } else if ((p = srchWord(row, "BEGIN")) != NULL || (p = strchr(row, '{')) != NULL) { unit = getUnitSize(fh, fnt); if (ncm < 0) ncm = unit.cy + 8; strcpy(dnm, did); if (!strncmp(dnm, "IDD_", 4)) { strcpy(dnm, did + 4); strlowcase(dnm); } sprintf(buf, "Dim Shared %s As GtkWidget Ptr\n", dnm); decl += buf; decl += "Dim Shared vbox As GtkWidget Ptr\n"; decl += "Dim Shared fixed As GtkWidget Ptr\n"; decl += "Dim font_desc As PangoFontDescription Ptr\n"; sprintf(buf,"%s = gtk_window_new(GTK_WINDOW_TOPLEVEL)\n", dnm); impl += buf; sprintf(buf,"gtk_window_set_resizable(GTK_WINDOW(%s), TRUE)\n", dnm); impl += buf; sprintf(buf,"gtk_widget_set_size_request(%s, %d, %d)\n", dnm, w * unit.cx / 4, h * unit.cy / 8 + ncm); impl += buf; sprintf(buf,"gtk_window_set_position (GTK_WINDOW(%s), GTK_WIN_POS_NONE)\n", dnm); impl += buf; sprintf(buf,"gtk_window_set_title (GTK_WINDOW(%s), %s)\n", dnm, cap); impl += buf; impl += "vbox = gtk_vbox_new(FALSE,2)\n"; if (strcmp(mnm,"NULL")) { sprintf(buf,"gtk_box_pack_start(GTK_BOX(vbox), %s, FALSE, FALSE, 0)\n", mnm); impl += buf; } sprintf(buf,"gtk_container_add(GTK_CONTAINER(%s), vbox)\n", dnm); impl += buf; impl += "fixed = gtk_fixed_new()\n"; sprintf(buf,"font_desc = pango_font_description_from_string(\"%s %d\")\n",fnt,fh); impl += buf; impl += "\n'Controls\n"; while(fgets(row, sizeof(row),f)) { if ((p = srchWord(row, "PUSHBUTTON")) != NULL) { control(1, p + 10, "button", "BS_PUSHBUTTON Or WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "DEFPUSHBUTTON")) != NULL) { control(1, p + 13, "button", "BS_DEFPUSHBUTTON Or WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "AUTOCHECKBOX")) != NULL) { control(1, p + 12, "button", "BS_AUTOCHECKBOX Or WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "AUTORADIOBUTTON")) != NULL) { control(1, p + 15, "button", "BS_AUTORADIOBUTTON Or WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "GROUPBOX")) != NULL) { control(1, p + 8, "button", "BS_GROUPBOX Or WS_CHILD Or WS_VISIBLE", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "EDITTEXT")) != NULL) { control(0, p + 8, "edit", "WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "LTEXT")) != NULL) { control(1, p + 5, "static", "WS_CHILD Or WS_VISIBLE", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "LISTBOX")) != NULL) { control(0, p + 7, "listbox", "WS_CHILD Or WS_VISIBLE", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = srchWord(row, "COMBOBOX")) != NULL) { control(0, p + 8, "combobox", "WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if ((p = strstr(row, "CONTROL")) != NULL) { control(2, p + 7, "", "WS_CHILD Or WS_VISIBLE Or WS_TABSTOP", dnm, &unit, decl, impl, dclproc, procs); } else if (strstr(row, "END") != NULL || strchr(row, '}') != NULL) { break; } } impl += "gtk_container_add(GTK_CONTAINER(vbox), fixed)\n"; sprintf(buf,"g_signal_connect (G_OBJECT(%s), \"destroy\", G_CALLBACK(@%s_destroy),NULL)\n", dnm,dnm); impl += buf; procgen(dnm, "destroy", dclproc, procs); } } } else if ((p = srchWord(row, "MENU")) != NULL || (p = srchWord(row, "MENUEX")) != NULL) { decl += "' declare menu\n"; menu += "' menu\n"; int n = decl.size() - 1; p = strtok(row, " "); strcpy(mnm, p); if (!strncmp(mnm, "IDR_", 4)) { strcpy(mnm, p + 4); strlowcase(mnm); } procmenu(p+4, mnm, decl, menu, dclproc, procs, f, 0); } } fclose(f); //printf("'code generated.\n"); //printf("'template loaded.\n"); printf("#include \"gtk/gtk.bi\"\n\n"); printf( "sub child_set_font_callback cdecl(widget As GtkWidget Ptr, gdata As gpointer)\n" " gtk_widget_modify_font(GTK_WIDGET(widget), Cast(PangoFontDescription Ptr, gdata))\n" "end sub\n" "sub child_set_font(widget As GtkWidget Ptr, font_desc As PangoFontDescription Ptr)\n" " gtk_container_foreach(GTK_CONTAINER(widget), Cast(GtkCallback, @child_set_font_callback), " "Cast(gpointer, font_desc))\n" "end sub\n\n" ); printf("%s\n", decl.c_str()); printf("%s\n", dclproc.c_str()); printf("gtk_init(NULL,NULL)\n\n"); printf("%s\n", menu.c_str()); printf("%s\n", impl.c_str()); printf("gtk_widget_show_all(%s)\ngtk_main()\n", dnm); printf("\n'-------------------------------------------\n\n"); printf("%s\n", procs.c_str()); }