Guest User

HyperHacker

a guest
Jan 11th, 2010
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.57 KB | None | 0 0
  1. /* Convert Widget by HyperHacker - A tiny base conversion utility.
  2.  * Jan 10, 2010
  3.  * Email: the aforementioned name, at gmail, dot com.
  4.  * Not tested on Windows.
  5.  * Makefile: http://pastebin.com/f7a68f3
  6.  */
  7. #ifndef __STDC_FORMAT_MACROS
  8. #define __STDC_FORMAT_MACROS //for inttypes.h to actually do anything useful
  9. #endif
  10.  
  11. //Library includes
  12. #include <gtk/gtk.h>
  13. #include <inttypes.h> //64-bit printf macros
  14. #include <stdio.h>
  15. #include <string.h>
  16. typedef uint64_t u64;
  17.  
  18. //Function prototypes
  19. int main(int argc, char** argv);
  20. static gboolean MainWindow_DeleteEvent(GtkWidget *Widget, GdkEvent *Event,
  21.     gpointer Unused);
  22. static void SetBoxes(u64 Val);
  23. static void NumBox_Activate(GtkEntry *Entry, gpointer Fmt);
  24.    
  25. //Constants
  26. const char *Labels = "SUHBOFD";
  27. const char *Tooltips[] = {"Signed Decimal", "Unsigned Decimal", "Hexadecimal",
  28.     "Binary", "Octal", "Float", "Double"};
  29. const char *Formats[] = {"%" SCNd64, "%" SCNu64, "%" SCNx64, NULL, "%o", "%f",
  30.     "%lf"};
  31.    
  32. //Globals (oh noes)
  33. GtkWidget *MainWindow, *TextBox[7];
  34.  
  35. //Options
  36. bool Pad = true, Lowercase = false;
  37. int FloatDecimals = 6;
  38.  
  39. /* Entry point.
  40.  */
  41. int main(int argc, char **argv)
  42. {
  43.     gtk_init(&argc, &argv);
  44.     unsigned int BoxSize = 8;
  45.     unsigned int ShowFields = ~0;
  46.    
  47.     //Parse command line
  48.     for(int i=1; i<argc; i += 2)
  49.     {
  50.         char *Opt = argv[i];
  51.         for(int j=0; (j<2) && (Opt[0] == '-'); j++) Opt = &Opt[1];
  52.         if((i+1) >= argc) Opt[0] = 'h';
  53.         switch(Opt[0])
  54.         {
  55.             case 's':
  56.                 ShowFields = 0;
  57.                 for(int j=0; argv[i+1][j] != '\0'; j++)
  58.                     for(int f=0; Labels[f] != '\0'; f++)
  59.                         if(Labels[f] == argv[i+1][j])
  60.                             ShowFields |= (1 << f);
  61.                 if(!ShowFields) ShowFields = ~0;
  62.             break;
  63.            
  64.             case 'd':
  65.                 sscanf(argv[i+1], "%d", &FloatDecimals);
  66.                 if(FloatDecimals > 507) FloatDecimals = 507;
  67.                 //this is the longest a double can hold so any more will just
  68.                 //be trailing zeros
  69.             break;
  70.            
  71.             case 'p': Pad = argv[i+1][0] == '1'; break;
  72.             case 'l': Lowercase = argv[i+1][0] == '1'; break;
  73.            
  74.             default:
  75.                 printf(
  76. "Converter v%u (%u-%02u-%02u #%u) by HyperHacker\n"
  77. "Options:\n"
  78. "-s %s: Show only the specified fields:\n"
  79. "   S=Signed Decimal   U=Unsigned Decimal   H=Hexadecimal   B=Binary\n"
  80. "   O=Octal            F=Float              D=Double\n"
  81. "   e.g. -s UHB will display only unsigned, hex, binary.\n"
  82. "   Default is to show all fields.\n"
  83. "-d n: Display n decimals in float/double fields.\n"
  84. "-p n: Enable (n=1) or disable (n=0) zero-padding. Default is %d.\n"
  85. "-l n: Use (n=1) or don't use (n=0) lowercase hex. Default is %d.\n"
  86. "Due to GTK limitations, the boxes do not update as you type;\n"
  87. "you must press enter to convert.\n",
  88.                     BUILD_ID, BUILD_YEAR+2000, BUILD_MONTH, BUILD_DAY,
  89.                     BUILD_INDEX, Labels, Pad, Lowercase);
  90.             return 0;
  91.         }
  92.     }
  93.    
  94.     //Create window
  95.     MainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  96.     gtk_window_set_title(GTK_WINDOW(MainWindow), "Convertor");
  97.     gtk_signal_connect(GTK_OBJECT(MainWindow), "delete-event",
  98.         (GtkSignalFunc)MainWindow_DeleteEvent, NULL);
  99.    
  100.     GtkWidget *Container = gtk_vbox_new(false, 0);
  101.     gtk_container_add(GTK_CONTAINER(MainWindow), Container);
  102.    
  103.     for(int i=0; Labels[i]; i++)
  104.     {
  105.         //Even if we don't show it, we still create the box, so we don't have to
  106.         //worry about whether it exists later.
  107.         //If it's not being shown, we just don't add it anywhere.
  108.         char Lbl[2] = {Labels[i], '\0'};
  109.         TextBox[i] = gtk_entry_new();
  110.         gtk_entry_set_width_chars(GTK_ENTRY(TextBox[i]), BoxSize);
  111.         gtk_signal_connect(GTK_OBJECT(TextBox[i]), "activate",
  112.             (GtkSignalFunc)NumBox_Activate, (void*)Formats[i]);
  113.         gtk_widget_set_tooltip_text(TextBox[i], Tooltips[i]);
  114.        
  115.         if(!(ShowFields & (1 << i))) continue;
  116.        
  117.         GtkWidget *B = gtk_hbox_new(false, 0);
  118.         gtk_box_pack_start(GTK_BOX(Container), B, false, false, 0);
  119.         gtk_box_pack_start(GTK_BOX(B), gtk_label_new(Lbl),
  120.             false, false, 0);
  121.         gtk_box_pack_end(GTK_BOX(B), TextBox[i], true, true, 0);
  122.     }
  123.    
  124.     //Enter main loop
  125.     gtk_widget_show_all(MainWindow);
  126.     gtk_main(); //main loop should never return
  127.     return 0; //but compilers like it if we do this anyway
  128. }
  129.  
  130. /* Callback for MainWindow delete_event (window was closed).
  131.  * Inputs:
  132.  * -Widget: Widget that received the event (i.e. the GTK Window).
  133.  * -Event: The event.
  134.  * Returns: TRUE to stop other handlers, FALSE to propagate further.
  135.  */
  136. static gboolean MainWindow_DeleteEvent(GtkWidget *Widget, GdkEvent *Event,
  137.     gpointer Unused)
  138. {
  139.     gtk_exit(0);
  140.     return TRUE;
  141. }
  142.  
  143. /* Sets the value of all boxes.
  144.  * Inputs:
  145.  * -Val: Value to set.
  146.  */
  147. static void SetBoxes(u64 Val)
  148. {
  149.     //This buffer is huge because double values can be ~507 digits and the user
  150.     //can set the number of decimals desired
  151.     char Buf[1024];
  152.    
  153.     //SDec
  154.     sprintf(Buf, "%" PRId64, Val);
  155.     gtk_entry_set_text(GTK_ENTRY(TextBox[0]), Buf);
  156.    
  157.     //UDec
  158.     sprintf(Buf, "%" PRIu64, Val);
  159.     gtk_entry_set_text(GTK_ENTRY(TextBox[1]), Buf);
  160.    
  161.     //Hex
  162.     Buf[0] = '0';
  163.     sprintf(&Buf[1], Lowercase ? "%" PRIx64 : "%" PRIX64, Val);
  164.     char *Res = (Pad && (strlen(&Buf[1]) & 1)) ? Buf : &Buf[1];
  165.     gtk_entry_set_text(GTK_ENTRY(TextBox[2]), Res);
  166.    
  167.     //Oct
  168.     Buf[0] = '0'; Buf[1] = '0';
  169.     sprintf(&Buf[2], "%" PRIo64, Val);
  170.     Res = &Buf[2] - (Pad ? (2 - ((strlen(&Buf[2]) - 1) % 3)) : 0);
  171.     gtk_entry_set_text(GTK_ENTRY(TextBox[4]), Res);
  172.    
  173.     //Float
  174.     //If FloatDecimals is 1 it leaves out the number of decimals, which SHOULD
  175.     //mean show ALL decimal places, but instead it insists on using 6. :-/
  176.     //so we'll just override it:
  177.     if(FloatDecimals < 0) FloatDecimals = 500;
  178.     char Fmt[64] = "%", *End;
  179.     if(FloatDecimals >= 0) sprintf(Fmt, "%%.%u", FloatDecimals);
  180.     End = strchr(Fmt, '\0');
  181.     End[0] = 'F'; End[1] = '\0';
  182.     sprintf(Buf, Fmt, *(float*)(void*)&Val);
  183.     gtk_entry_set_text(GTK_ENTRY(TextBox[5]), Buf);
  184.    
  185.     //Double
  186.     End[0] = 'l'; End[1] = 'f'; End[2] = '\0';
  187.     sprintf(Buf, Fmt, *(double*)(void*)&Val);
  188.     gtk_entry_set_text(GTK_ENTRY(TextBox[6]), Buf);
  189.    
  190.     //Bin
  191.     int i = 0;
  192.     for(; Val || ((Val && !Pad) || !i || (Pad && (i & 7))); i++)
  193.     {
  194.         Buf[(sizeof(Buf) - 2) - i] = '0' + (Val & 1);
  195.         Val >>= 1;
  196.     }
  197.     Buf[sizeof(Buf) - 1] = '\0';
  198.     gtk_entry_set_text(GTK_ENTRY(TextBox[3]), &Buf[(sizeof(Buf) - 1) - i]);
  199. }
  200.  
  201. /* Activate signal for textboxes.
  202.  * Inputs:
  203.  * -Entry: The textbox.
  204.  * -Fmt: The format string to read it with.
  205.  */
  206. static void NumBox_Activate(GtkEntry *Entry, gpointer Fmt)
  207. {
  208.     const gchar *Str = gtk_entry_get_text(Entry);
  209.     u64 Val = 0;
  210.     if(Fmt) sscanf(Str, (const char*)Fmt, &Val);
  211.     else //binary
  212.     {
  213.         unsigned int n = 0;
  214.         for(int i = strlen(Str) - 1; i >= 0; i--, n++)
  215.             Val |= ((Str[i] == '1') ? 1 : 0) << n;
  216.     }
  217.     SetBoxes(Val);
  218. }
Add Comment
Please, Sign In to add comment