Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Convert Widget by HyperHacker - A tiny base conversion utility.
- * Jan 10, 2010
- * Email: the aforementioned name, at gmail, dot com.
- * Not tested on Windows.
- * Makefile: http://pastebin.com/f7a68f3
- */
- #ifndef __STDC_FORMAT_MACROS
- #define __STDC_FORMAT_MACROS //for inttypes.h to actually do anything useful
- #endif
- //Library includes
- #include <gtk/gtk.h>
- #include <inttypes.h> //64-bit printf macros
- #include <stdio.h>
- #include <string.h>
- typedef uint64_t u64;
- //Function prototypes
- int main(int argc, char** argv);
- static gboolean MainWindow_DeleteEvent(GtkWidget *Widget, GdkEvent *Event,
- gpointer Unused);
- static void SetBoxes(u64 Val);
- static void NumBox_Activate(GtkEntry *Entry, gpointer Fmt);
- //Constants
- const char *Labels = "SUHBOFD";
- const char *Tooltips[] = {"Signed Decimal", "Unsigned Decimal", "Hexadecimal",
- "Binary", "Octal", "Float", "Double"};
- const char *Formats[] = {"%" SCNd64, "%" SCNu64, "%" SCNx64, NULL, "%o", "%f",
- "%lf"};
- //Globals (oh noes)
- GtkWidget *MainWindow, *TextBox[7];
- //Options
- bool Pad = true, Lowercase = false;
- int FloatDecimals = 6;
- /* Entry point.
- */
- int main(int argc, char **argv)
- {
- gtk_init(&argc, &argv);
- unsigned int BoxSize = 8;
- unsigned int ShowFields = ~0;
- //Parse command line
- for(int i=1; i<argc; i += 2)
- {
- char *Opt = argv[i];
- for(int j=0; (j<2) && (Opt[0] == '-'); j++) Opt = &Opt[1];
- if((i+1) >= argc) Opt[0] = 'h';
- switch(Opt[0])
- {
- case 's':
- ShowFields = 0;
- for(int j=0; argv[i+1][j] != '\0'; j++)
- for(int f=0; Labels[f] != '\0'; f++)
- if(Labels[f] == argv[i+1][j])
- ShowFields |= (1 << f);
- if(!ShowFields) ShowFields = ~0;
- break;
- case 'd':
- sscanf(argv[i+1], "%d", &FloatDecimals);
- if(FloatDecimals > 507) FloatDecimals = 507;
- //this is the longest a double can hold so any more will just
- //be trailing zeros
- break;
- case 'p': Pad = argv[i+1][0] == '1'; break;
- case 'l': Lowercase = argv[i+1][0] == '1'; break;
- default:
- printf(
- "Converter v%u (%u-%02u-%02u #%u) by HyperHacker\n"
- "Options:\n"
- "-s %s: Show only the specified fields:\n"
- " S=Signed Decimal U=Unsigned Decimal H=Hexadecimal B=Binary\n"
- " O=Octal F=Float D=Double\n"
- " e.g. -s UHB will display only unsigned, hex, binary.\n"
- " Default is to show all fields.\n"
- "-d n: Display n decimals in float/double fields.\n"
- "-p n: Enable (n=1) or disable (n=0) zero-padding. Default is %d.\n"
- "-l n: Use (n=1) or don't use (n=0) lowercase hex. Default is %d.\n"
- "Due to GTK limitations, the boxes do not update as you type;\n"
- "you must press enter to convert.\n",
- BUILD_ID, BUILD_YEAR+2000, BUILD_MONTH, BUILD_DAY,
- BUILD_INDEX, Labels, Pad, Lowercase);
- return 0;
- }
- }
- //Create window
- MainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(MainWindow), "Convertor");
- gtk_signal_connect(GTK_OBJECT(MainWindow), "delete-event",
- (GtkSignalFunc)MainWindow_DeleteEvent, NULL);
- GtkWidget *Container = gtk_vbox_new(false, 0);
- gtk_container_add(GTK_CONTAINER(MainWindow), Container);
- for(int i=0; Labels[i]; i++)
- {
- //Even if we don't show it, we still create the box, so we don't have to
- //worry about whether it exists later.
- //If it's not being shown, we just don't add it anywhere.
- char Lbl[2] = {Labels[i], '\0'};
- TextBox[i] = gtk_entry_new();
- gtk_entry_set_width_chars(GTK_ENTRY(TextBox[i]), BoxSize);
- gtk_signal_connect(GTK_OBJECT(TextBox[i]), "activate",
- (GtkSignalFunc)NumBox_Activate, (void*)Formats[i]);
- gtk_widget_set_tooltip_text(TextBox[i], Tooltips[i]);
- if(!(ShowFields & (1 << i))) continue;
- GtkWidget *B = gtk_hbox_new(false, 0);
- gtk_box_pack_start(GTK_BOX(Container), B, false, false, 0);
- gtk_box_pack_start(GTK_BOX(B), gtk_label_new(Lbl),
- false, false, 0);
- gtk_box_pack_end(GTK_BOX(B), TextBox[i], true, true, 0);
- }
- //Enter main loop
- gtk_widget_show_all(MainWindow);
- gtk_main(); //main loop should never return
- return 0; //but compilers like it if we do this anyway
- }
- /* Callback for MainWindow delete_event (window was closed).
- * Inputs:
- * -Widget: Widget that received the event (i.e. the GTK Window).
- * -Event: The event.
- * Returns: TRUE to stop other handlers, FALSE to propagate further.
- */
- static gboolean MainWindow_DeleteEvent(GtkWidget *Widget, GdkEvent *Event,
- gpointer Unused)
- {
- gtk_exit(0);
- return TRUE;
- }
- /* Sets the value of all boxes.
- * Inputs:
- * -Val: Value to set.
- */
- static void SetBoxes(u64 Val)
- {
- //This buffer is huge because double values can be ~507 digits and the user
- //can set the number of decimals desired
- char Buf[1024];
- //SDec
- sprintf(Buf, "%" PRId64, Val);
- gtk_entry_set_text(GTK_ENTRY(TextBox[0]), Buf);
- //UDec
- sprintf(Buf, "%" PRIu64, Val);
- gtk_entry_set_text(GTK_ENTRY(TextBox[1]), Buf);
- //Hex
- Buf[0] = '0';
- sprintf(&Buf[1], Lowercase ? "%" PRIx64 : "%" PRIX64, Val);
- char *Res = (Pad && (strlen(&Buf[1]) & 1)) ? Buf : &Buf[1];
- gtk_entry_set_text(GTK_ENTRY(TextBox[2]), Res);
- //Oct
- Buf[0] = '0'; Buf[1] = '0';
- sprintf(&Buf[2], "%" PRIo64, Val);
- Res = &Buf[2] - (Pad ? (2 - ((strlen(&Buf[2]) - 1) % 3)) : 0);
- gtk_entry_set_text(GTK_ENTRY(TextBox[4]), Res);
- //Float
- //If FloatDecimals is 1 it leaves out the number of decimals, which SHOULD
- //mean show ALL decimal places, but instead it insists on using 6. :-/
- //so we'll just override it:
- if(FloatDecimals < 0) FloatDecimals = 500;
- char Fmt[64] = "%", *End;
- if(FloatDecimals >= 0) sprintf(Fmt, "%%.%u", FloatDecimals);
- End = strchr(Fmt, '\0');
- End[0] = 'F'; End[1] = '\0';
- sprintf(Buf, Fmt, *(float*)(void*)&Val);
- gtk_entry_set_text(GTK_ENTRY(TextBox[5]), Buf);
- //Double
- End[0] = 'l'; End[1] = 'f'; End[2] = '\0';
- sprintf(Buf, Fmt, *(double*)(void*)&Val);
- gtk_entry_set_text(GTK_ENTRY(TextBox[6]), Buf);
- //Bin
- int i = 0;
- for(; Val || ((Val && !Pad) || !i || (Pad && (i & 7))); i++)
- {
- Buf[(sizeof(Buf) - 2) - i] = '0' + (Val & 1);
- Val >>= 1;
- }
- Buf[sizeof(Buf) - 1] = '\0';
- gtk_entry_set_text(GTK_ENTRY(TextBox[3]), &Buf[(sizeof(Buf) - 1) - i]);
- }
- /* Activate signal for textboxes.
- * Inputs:
- * -Entry: The textbox.
- * -Fmt: The format string to read it with.
- */
- static void NumBox_Activate(GtkEntry *Entry, gpointer Fmt)
- {
- const gchar *Str = gtk_entry_get_text(Entry);
- u64 Val = 0;
- if(Fmt) sscanf(Str, (const char*)Fmt, &Val);
- else //binary
- {
- unsigned int n = 0;
- for(int i = strlen(Str) - 1; i >= 0; i--, n++)
- Val |= ((Str[i] == '1') ? 1 : 0) << n;
- }
- SetBoxes(Val);
- }
Add Comment
Please, Sign In to add comment