Tuesday, December 2, 2008
Overlaying windows over GTK Window
1.) Modifying vncdisplay.c to emmit signals to the program.
2.) Inserting a one pixel high button on top to catch events.
Both methods has its pros and cons. By using method 1, we will be able to see the entire screen. But by using method 1 also, we will be required to modify the source of the original code (the codebase i was using is gtk-vnc-0.3.7).
In order to stear clear from modifying the author's code, the best way round this is to use method 2, which is to insert a single pixel button on top of the vnc viewer so that we can catch events instead of catching signals. The codes are fairly simple. But this is rather tricky to do because what happens when the mouse leaves the button? The button will close immediately. So, there needs to be a sleep event right?
No, GTK doesn't like sleeping.. somehow.. there will be an error, but I managed to overcome this stupid problem (look at the earlier post for details). But actually the best way to do this is to use an alarm signals.
The idea is as follows:
1.) If the cursor is above the single pixel button, show the disconnect button.
2.) Once the cursor leaves, it, create a signal alarm of 2.
3.) In the event of the signal 'rings' after 2 seconds, we hide the disconnect button.
With that said, the codes are:
// create another window above an existing window
popWindow = gtk_window_new(GTK_WINDOW_POPUP);
// show and hide windows in GTK
void showMenu (GtkWidget *vncdisplay, GdkEventMotion *event) {
gtk_widget_show(popWindow);
}
void choseMenu (GtkWidget *vncdisplay, GdkEventMotion *event) {
signal(SIGALRM, catch_alarm);
alarm(2);
}
// alarm function
void catch_alarm() {
gtk_widget_hide(popWindow);
alarm(0);
}
// signals
gtk_signal_connect(GTK_OBJECT(myButton), "enter", GTK_SIGNAL_FUNC(showMenu), window);
gtk_signal_connect(GTK_OBJECT(myButton), "leave", GTK_SIGNAL_FUNC(hideMenu), window);
Getting coordinates of cursor in GTK
gint x, y;
gdk_window_get_pointer(window->window, &x, &y, 0);
printf("My cords are: x %d and y: %d", x, y);
Viola!
GTK Error When forking
To resolve this, make sure that we exit the child using: _exit (-1), instead of the normal exit function.
Monday, November 24, 2008
Dumping output of a program
system ("SSH 192.168.1.102 1> /dev/null 2> /dev/null");
Basically 1> /dev/null means dump all the output of the program to /dev/null
and 2> /dev/null means dump all the error output to /dev/null
Monday, November 17, 2008
Research on Netstat
So my first stop was really to play around with netstat. And I found a very interesting behaviour when vncviewer is connecting to a vncserver through an SSH tunnel.
Setup:
I started port forwarding: SSH -L 10001:localhost:5900
Then. with the command: netstat -t grep
Observations:
1.) When RECV-Q is = 0, it means there is no user activity in SSH
2.) When RECV-Q is > 0, it means there is user activity
3.) When SEND-Q is = 0 or > 1504, it means SSH connection is active and host is alive.
4.) When SEND-Q is = 1504, it means SSH connection is active, but host is dead.
Sunday, November 16, 2008
PHP Session Manipulation
Well this question actually brings two more questions in my mind instantly:
1.) Is PHP session information stored only on the server?
We can't actually manipulate PHP information that resides on the server, it is just not really possible security wise. But what we can do is manipulate it in such a way that we can resume it even after it dies when garbage collector destroys it.
2.) How is PHP Session stored on the server? On disk or in memory?
The first time you call session_start(), PHP basically generates a new session ID and creates an empty file to store session variables. PHP also sends a cookie back to the client that contains the session ID.
There are a couple of techniques to session resumption.
1.) Cookies - Store session information into cookie as it is being stored on the session variable. That way, when we resume our session after we close the browser window, we can first of all check if there was a cookie set, and if there is, read that cookie information to the session and start.
2.) Database - Store session information into database as it is being stored on the session variable. Similar to the cookie approach, but this is preferred because it is really permanent and it does not rely on the client's cookie function (some client disable cookies on their browser).
3.) Mixture of Cookies + Database. Cookies is faster than database but database is more persistent than a cookie. Therefore, a mixture of this techniques allows for a persistent and fast session resumption.
Saturday, November 15, 2008
Firefox Flex Error
To build files into your bin-release folder you have to choose the "Build Release" option inside Flex. This will essentailyl ask Flex to build a release for real usage and not for debugging purposes.
Whitespaces in flex
Flex's Error #2048: Security sandbox violation
To get around this problem, you have three choices:
- Add a crossdomain.xml file to the server with the data.
- Upload your SWF file to the same server as the data service.
- Create a proxy on your server that calls the data service, and put your SWF file on the same server as the proxy.
The simplest method is to create a crossdomain.xml file. The instructions are:
A crossdomain.xml file is an XML file that provides a way for a server to indicate that its data and documents are available to SWF files served from certain domains, or from all domains. The crossdomain.xml file must be in the web root of the server that the Flex application is contacting. For more information about configuring crossdomain.xml files, see the technote on the Macromedia website: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_14213.
Tuesday, November 11, 2008
How to check if VNCClient is connecting to VNCServer
I was having the problem of the vncserver having too many 'alive' connections because vncclients were being killed abruptly and there is no build in methodology for vncserver that kills the vncserver if nobody is connecting to it. I was toying around with TCPKeepAlive and stuffs, but that didn't really work out fine.
One of the ways to do so if you have access to both the VNCServer and VNCClient codes is to use the ping-pong approach. In the sense that the VNCClient will constantly contact the VNCServer to tell him that it exist. If it does not for after a predefined time limit, you can take for granted that there is either a network problem of VNCClient is not listening to the server anymore. Building it is really quite simple:
1.) create a program call "vncinform" on the remote server. Basically it receives a request from a unique identifier (i.e. an ip address). and update the timestamp of a file.
2.) modify the vncviwer to call "vncinform" remotely using ssh. For example SSH
3.) on the end of the vncserver, create a cron job to kill the vncserver session if the timestamp for a particular host is more than a predefined amount of time.
Done!
Monday, November 10, 2008
php.ini file upload size
I am writing the php.ini file for file upload size. (by default php sets it at 2MB).
So basically these are the steps:
1.) Open Notepad
2.) Type this in:
post_max_size = 10000000
upload_max_filesize = 10000000
10000000 = 10 MB
3.) Save, upload this file to the server, into the folder where your upload script resides.
DONE!
.htaccess won't work with some of the shared hosting companies, so my method is the way to go :)
if you want .htaccess may work for some:
php_value memory_limit 150M
php_value post_max_size 100M
php_value upload_max_filesize 50M
php_value max_execution_time 600
Thursday, November 6, 2008
Collapsing/ Hiding rows in a table
<script type="text/javascript">
var hide= true;
function toggleRows(tableId, rowId, tag){
tbl = document.getElementById(tableId);
navispan = document.getElementById(rowId);
var len = tbl.rows.length; if(tag.innerHTML.substring(0,4) == "Show") {
navispan.innerHTML = tag.innerHTML.substring(5); hide= false;
} else {
navispan.innerHTML = "Show " + tag.innerHTML; hide= true;
}
var vStyle = (hide)? "none":"";
tbl.rows[rowId].style.display = vStyle;
}</script>
<style>
.header {
text-align:left; width:100px;
}
.bodyText {
width:150x;
}
</style>
</head>
<body>
Click here to hide/show
<span id="0" onClick='toggleRows("myTable",0, this)' style='cursor:pointer;color:#cc0000'>Aaron</span>
<span id="1" onClick='toggleRows("myTable",1, this)' style='cursor:pointer;color:#cc0000'>Jason</span> <span id="2" onClick='toggleRows("myTable",2, this)' style='cursor:pointer;color:#cc0000'>Adam</span>
<br /><br />
<table id="myTable" style="width:400px; border:0px;">
<tbody>
<tr>
<td class="header"> <span onClick='toggleRows("myTable",0, this)' style='cursor:pointer;color:#cc0000'>Aaron</span> </td>
<td class="bodyText"> This annotation Sucks </td>
<td class="bodyText"> This annotation is good </td>
</tr> <tr>
<td class="header"> <span onClick='toggleRows("myTable",1, this)' style='cursor:pointer;color:#cc0000'>Jason</span> </td>
<td class="bodyText"> </td> <td class="bodyText"> This annotation cannot make it. </td> </tr> <tr>
<td class="header"> <span onClick='toggleRows("myTable",2, this)' style='cursor:pointer;color:#cc0000'>Adam</span> </td>
<td class="bodyText"> I love this phrase </td> <td class="bodyText"> This phrase is dumb. </td> </tr>
</tbody>
</table>
Getting output from a remote program using PERL + SSH
Basically what I was trying to do is establish an ssh connection, get a port that is open on that server, and return it back to the connecting server. What you will need is really two portions of a code, first off, a program on the server that returns the port, it can be as simple as print "PORT=21"; then secondly you need the code shown below that calls the remote program above:
my @remote_stdout = split("\n", `ssh $user\@$host '"<cmd>"'`);
if($? != 0) {
warn ":ERROR: could not establish ssh connection with '$host' host";
} else {
my $last_stdout_line = pop @remote_stdout;
my $remote_command_result;
if(defined $last_stdout_line and ($last_stdout_line =~ m/^PORT=(\d+)$/)) {
$remote_command_result = $1;
}
if(defined $remote_command_result) {
warn ":Port Found: $remote_command_result";
} else {
warn ":ERROR: no results";
}
}
Establish SSH Tunnel and run VNCViewer using Perl
Using perl, I was trying to run SSH Tunnel first and then run VNCViewer through this tunnel. Of course it was not so simple as to just doing the following in perl:
#!/usr/bin/perl
system("ssh -l
system("vncviewer localhost:10000");
If you try to do the above, it won't work! This is because the process gets stuck on the first line while in SSH. Basically if the tunnel is active, it can't possibly run the next command which is to launch vncviewer. But if the tunnel is terminated, so that we can run vncviewer, vncviewer won't work because there is no more binding on port 10000.
We need to use perls' build in fork function. Similar to running programs using the trailing & command in C. My implementation (thanks to estabroo from LQ) is as follows:
$pid = fork();
if ($pid == 0) {
system("ssh -l
exit(0);
} elsif ($pid > 0) {
sleep(5);
system("vncviewer localhost:10000");
} else {
print "fork failed\n";
}
Running VNCViewer using SSH Port Fowarding
I would like to start an SSH tunnel and then run vncviewer to connect the port. But as we all know, vncviewer pretty much sends everything in clear over the network, we have to introduce some 'security' to it. One common way is using SSH. In linux, its as simple as just two lines:
ssh -l
vncviewer localhost:10000
*in order for this work, you need to have vncserver already setup and serving on port 5901.
That's it! What it is tryinng to do is. Listen locally on port 10000 and forward any incoming connection to port 5901 of the remotehost. Localhost here pretty much refers to the remote host. It does not make any difference if you were to run the command as, it should still work:
ssh -l
Done. I will be posting shortly on how I did this in perl.
Perl script for vncpasswd
But the problem with VNCpasswd is that it requires users to input by prompt and I would like to automate this process of password encryption using VNCpasswd. How do we do it then? We have to create a perl script wrapper around the xvnc.
VNCpasswd itself was written using C++. I downloaded the source codes of VNCpasswd using the following command:
apt-get source xvnc4viewer
Basically, inside the unix/ folder, you can find all source codes for vncpasswd, vncviewer, vnconnect etc. Looking into vncpasswd, you will realise vncpasswd use a few common functions inside the common/rfb folder, namely 'd3des.c' and 'Password.cxx'. Looking into the codes of Password.cxx, you will realise that the vncpasswd basically uses DES with a plain text key of {23, 82, 107, 6, 35, 78, 88, 7}.
Logically, I thought that it was easy to do so. And I should be able to to technically perform the same operation using the built-in Perl DES library. My code for this were as follows:
#!/usr/bin/perl
use Crypt::DES;
my $key = pack ('C8', 23,82,107,6,35,78,88,7);
my $cipher = Crypt::DES->new ($key);
$ciphertext = $cipher-$gt;encrypt('password');
$plaintext = $cipher-$gt;decrypt($ciphertext);
print "$plaintext is encrypted to become $ciphertext";
Simple enough, but the above codes didn't somehow match the codes that were given when i simply executte `vncpasswd password`. After much playing around, I decided to drop this approach. I am not sure if vncpasswd uses triple DES instead, either that or they created their own version of DES with slight differences.
Anyhow, I moved on and found that x11vnc actually allows you to create password using the -storepasswd option. In the following format:
x11vnc -storepassword
Viola! Problem 'technically' solved. Well, I can't create a wrapper for this. But since x11vnc solves my problem, why should I bother writting another perl script that performs the same functions? I rather spend my time optimizing my codes..
Make your screen stay when you click popup
<a href="#" onclick="javascript:win.. ">Click</a>
The reason why we have # here is because we want the cursor to show up so that on mouse over, the user knows that the link is 'clickable'. But by doing this, it will cause the page to reload. So how do we show the cursor but yet not cause the page to reload without.
The anwer is, don't use #, use CSS.
<p onClick="javascript:win.." style='cursor:pointer'>Click</p>
Problem Solve!
Saturday, November 1, 2008
Javascript Popup with Custom Controls in GridView ASP.NET
The codes are as follows:
<asp:TemplateField>
<HeaderTemplate>Manage</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink NavigateUrl='<%# DataBinder.Eval(Container,"DataItem.class_id", "javascript:window.open(\"classstudents.aspx?id={0}\",\"mywindow\",\"menubar=1,resizable=1,width=400,height=500\");") %>' Text="Manage" runat="server" Target="myBuffer"></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
The steps as usual are:
1. Create the objectdatasource
2. Creat the grdiview
3. Bind the objectdatasource to the gridview
4. Insert a TemplateColumn (when you select the grid and click edit column)
5. The templatecolumn should contain something liek the code above.
6. Done!
Take note that for javascript to work, it should be contained with a single quote. And if you need to display the quotes in javascript within asp.net, the escape character for asp.net C# is a backslash /
ASP.NET Custom Controls inside Gridview
CRUD: gridview, datalist
CRUD: detailsview (used really for 1 page paging purpsoe)
CR: listview, repeater
But adding a custom control i.e. placing your own dropdownlist inside a gridview can be tricky. Its not as simple as just binding an object as per normal. The codes are as follows:
<asp:TemplateField>
<HeaderTemplate>Active?</HeaderTemplate>
<ItemTemplate>
<asp:Label id="lblClass" runat="server" Text='<%# returnYesNoValue(DataBinder.Eval(Container,"DataItem.active", "{0}")) %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList id="ddlActive" SelectedValue='<%# Bind("active") %>' runat="server">
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="0">No</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
<HeaderStyle BorderStyle="None" />
<ItemStyle BorderStyle="None" />
</asp:TemplateField>
Steps:
1. Create an objectdatasource and link it with the a query from an XSD datafile.
2. Create a gridview and link it with the objectdatasource
3. Insert bound fileds and then insert the template fields
4. Go into the HTML code and then key in the codes above for the template area
5. As you can see its 'label' for viewmode and 'dropdownlist' for editmode
6. Make sure you bind the records with the value from db, and everything should work automatically.
Friday, October 24, 2008
Upload document in .NET C#
Part I: Storing in Database
a.) setup an input file with the name UploadFile.
<input id="UploadFile" type="file" runat="server">
b.) setup a button with the name btnUpload
<asp:imagebutton id="btnUpload" onclick="btnUpload_Click" runat="server" height="29" width="150" imageurl="images/buttons/upload_long.jpg"></asp:imagebutton>
c.) setup code behide for the button to be
if (Page.IsValid) {
String userId = Session["authenticated_userid"].ToString();
Stream imgStream = UploadFile.PostedFile.InputStream;
int imgLen = UploadFile.PostedFile.ContentLength;
byte[] imgBinaryData = new byte[imgLen];
int n = imgStream.Read(imgBinaryData, 0, imgLen);
DB.userTableAdapter aAdapter = new // you need to set this up in your own DB.xsd
DB.userTableAdapter();
int rowsAffected = aAdapter.UpdatePicture(imgBinaryData, int.Parse(userId));
if (rowsAffected > 0) {
Response.Redirect("home.aspx"); // go back to same page
}
}
Part II: Retrieving stored image from DB
1.) Create a file call getImage.aspx and inside Page Load
protected void Page_Load(object sender, EventArgs e) {
String userId = Session["authenticated_userId"].ToString(); // get your own identified
DB.userTableAdapter aAdapter = new DB.userTableAdapter();
byte [] temp = aAdapter.GetPicture(int.Parse(userId));
if (temp == null) // in case we find nothing in db {
Stream s = File.OpenRead(Server.MapPath("images\\portrait.jpg"));
temp = new byte[s.Length];
s.Read(temp, 0, (int)s.Length);
Response.BinaryWrite(temp);
s.Dispose();
s.Close();
}
Response.BinaryWrite(temp);
}
2.) Wherever you want to show you image, just call the image as per normal
i.e. <img src="http://www.blogger.com/getImage.aspx" />
Done! Enjoy.
ASP.NET (C#) unable to ENTER to submit form
1. Create a login function. i.e.
protected void login() {
// get database connection
// get variables from form
// check if correct, set session variable, redirect
// else, display error, return to form
}
2. In page load, use the following code:
If (Page.IsPostBack()) {
login();
}
Viola! Weird bug in ASP.NET i read. But yah, Page.IsPostBack fixes it all.
G1 Phone is out, but it will not take off.
But note, the fact that the phone (as a hardware) won't scale like that of Iphone, does not mean that the software(google apps etc) won't.
I believe Google, with their involvement in the Android opensource framework for mobile applications really show that they are in to revolutionize the way we use our phone, not so much to revolutionize phone. Of course, this might not seem feasible at a glance, but let's take a step back and see what happens if every phone is installed with Google Apps?
1. Their search hits will increased greatly, with the increased saturation of the online search market, this is their best way out to increase their market capture share - think about it, not everyone has a computer but most of us have a phone and that phones follows us everywhere. So far, not many search engines built applications that are meant for phones, and google i believe will continue to be the market leader in mobile and desktop searches for many years to come.
2. Increased advertisement sources. Instead of just being able to advertise for companies with an online presence (i.e. a website), Google will now be able to get business from small companies without any form of online presence. This is made possible by their ShopSavvy application (google app available from their g1 phone). There is now more reasons for these offline companies to advertise on Google.
3. Increased advertisement income. Google did an excellent job in increasing advertisement tagetting, in fact its so damn good, I click on the advertisements all the time. By being in the mobile phone industry, the software will be able to track where we are and feed to us advertisements that are more highly targeted. By being location-aware, the advertisements are getting more targeted and as a result, advertisers are definitely willing to pay a higher premium.
I believe the G1 phone will not really take off and capture a huge portion of the market. But one thing for sure, the softwares that google came up with, specifically google search, mail, maps and shopsavvy will revolutionize how we do our shopping and eventually our way of life.
I recalled from my economics class, that the professor once said. Economists like to think of the world in extreme scenarios that is, the market is either in a perfect or imperfect condition. In my humble opinion, with googleapps, information is getting perfect, we are not quite there yet, but we will one day.
I look forward to the day in my life that all barcodes are uniformlly standardized across the world. All product's barcodes uses electronic ink, compatible with RFID. All shops have a Standard Centralize Point of Sale System. If such a world exists, information of goods and services could then be truly perfect.
We are getting there, and googleapps - not the gphone. Will bring us there.
Monday, October 20, 2008
Saturday, October 11, 2008
Make borders around pictures
<style type="text/css">
.float img {
background: #fff;
border: solid 1px #ccc;
padding: 4px;
}
</style>
Here is a very good tutorial on creating frames:
http://www.csstemplatesweb.com/2008/05/08/web-20-design-generators/
Pictures with margins
<style type="text/css">
.float img {
float:left;
margin-bottom:10px;
margin-right:10px;
}
</style>
Done! The key property here is float, with it specified your picture will float to the left and your text will be on the right of this text with a margin of 10 pixels bottom and right to the picture. Natutally if you need it the reverse, you have to change float to right and the margin should be specified for left instead.
Multiline variable for javascript
Take for example
var temp = "This is Aaron"; //this works perfectly
var temp = "This\
is\
Aaron"; // this works with the /escape character
var temp = "This
is
Aaron"; // this does not work.
Now in order to solve it, I used PHP, after a bit of experiment, there are two approaches. I made used of (include + regex) and (file_get_contents + regex). Let's start with include + regex first.
var temp = "<?php $string = include('synopsis.php'); echo preg_replace("#(\r\n\n\r)#s", ' ', $string); ?>";
Inside the file: synopsis.php is a content like this:
$var = "This is Aaron";
return $var;
?>
This works perfectly fine, but its very cumbersome because you need to assign the variables and all.
I therefore came up with file_get_contents + regex. Inside the file:
var temp = "<?php $string = file_get_contents("synopsis.php"); echo preg_replace("#(\r\n\n\r)#s", ' ', $string); ?>";
Synopsis.php can contain any normal HTML, no need for customization like return.
This works great for me, what I was trying to do was to dynamically update the innerHTML variable of a DIV tag using javascript. The thing was that the content I wanted to update the DIV is multi line and with that javascript cannot work unless I manually edited each HTML page's source code to a single. This is definitely not very productive, for every change the client may want to make, i will have to edit it on Dreamweaver and go through line by line on notepad to make them a single line.
Hopefully this may help someone :)
Saturday, October 4, 2008
VMPlayer Remote Desktop Display
But they are essentially and some would argue that X11 is really not a thin client framework. (depending on how you define thin client). But anyhow, they are really different in the sense that VNC displays by pixel frame buffer refresh, it usually hosts a whole desktop (usually including a window manager) and reconnection to a lost connection would be simple as compared to X11.
Well, therefore I didn't had much choice and need to run VMPlayer using the VNC Protocol.
With the protocol settled, now I had to solve how to run multiple VMPlayer session on a computer and have it served simultaneously to different computers that connects to it. On top of that, computer 2 has to serve the client across the network to various clients remotely.
First of all, in computer 2(the server)
I have VMPlayer running in Linux, I added, the following lines to the VMX file, RemoteDesktop.add = "Enabled"
RemoteDesktop.port = "5901".
Then in computer 1(the client)
I have a VNC Player which will try to connect to port 5901 on Computer 2. Any normal VNC Player can run, e.g. UltraVNC or gtk-vnc (there is an example player for linux)
But VMPlayer does not render when we try to run it via a client. How do we actually run instance of VMPlayer remotely? I believe the answer lye in disabling the output of VMPlayer locally on the server. More research on this to come...
Wednesday, October 1, 2008
Looking for files inside Linux
$> find / -name *isr
Thursday, September 25, 2008
Segmentation Fault
For example if we do this in C,
char *s = "hello world";
*s = 'H';
When the program containing this code is compiled, the string "hello world" is placed in the section of the program binary marked as read-only; when loaded, the operating system places it with other strings and constant data in a read-only segment of memory. When executed, a variable, s, is set to point to the string's location, and an attempt is made to write an H character through the variable into the memory, causing a segmentation fault. (from wiki)
I had a similar problem such as:
char *s = "123";
int num = (int) *s;
I solved this problem using atoi(); which converts the ASCII characters into int.
char *s = "123";
int num = atoi(*s);
Monday, September 22, 2008
Makefiles in C
In a huge program, we tend to have many classes and dependencies (i.e. header files). For example, if we have a single program4 file which is make up of program1.c, program1.h which in turn make up program2.c together with program3.c to make the final program4 file.
In this example, the modification of program1.c will result in a recompilation of program1.c and program3.c which is technically inefficient. Imagine having to do this each time you are trying to debug and found a bug. So to make life easier, Makefile comes to the rescue. It basically automate compilation so that we don't have to type a long string of dependencies from scratch each time we make modification.
For a proper tutorial on how to create your own Makefile, visit:
http://www.eng.hawaii.edu/Tutor/Make/3.html
In very short term, in order to execute the makefile, run the command "make" inside a folder.
Yes, correct, just type "make" and hit ENTER. A chunk of output should normally appear, type "ls" and the executable program (normally in green) can be seen.
Compiling in C with Headers
A bit of details about header files, its similar to that of interface in java. Basically, its part of an object oriented concept that allows you to separate your program logic from other developers, the purpose really, is to allow other developers to know input and output information about your program (nothing much about the internal program logic) so as to allow other developers to develop their own program independently while you write your part.
Consider the following example:
We are trying to create a calculator program, we have a few programmers working on different components, one of which is multiplication. While developing the main calculator program (calculator.c), someone else can work on multiplication program logic (Multiplication.c). In a Multiplication there is an input of integer and and output of integer. Therefore, we can create a Multiplication.h file that specifies the method that the main calculator program developer should call in order to get the multiplied value of an input.
These are the files that forms the story above,
Multiplication.c
#include <stdio>
#include "Multiplication.h"
int getMultiply(int var1, int var2) {
return var1 * var2;
}
Multiplication.h
int getMultiply(int var1, int var2);
Calculator.c
#include <stdio>
#include "Multiplication.h"
int main() {
printf ("Result of 2 x 2: %d", getMultiply(2,2));
return 0;
}
As we can see clearly above, the method getMultiply inside Multiplication.h does not include any details of the internal logic of the multiplication method. To use a custom header, you have to include it within the main program as shown in line 2 of Calculator.c and call it as if the method is local within the program.
How do we actually compile the program?
1. compile the header's c files (not the header file):
gcc -c Multiplication.c
You can use the -c option with gcc to create the corresponding object (.o) file from a .c file. By specifying -c, the compiler will stop after the assembler stage, you will see that the output will be Multiplication.o.
2. compile the main program
gcc -o Calculator Calculator.c Multiplication.o
Here we specified the output to be called Calculator and we specified the input file of Multiplication.o which we generated from step1.
3. we can now run the program using:
./Calculator
If the program does not execute, and throws a permission error, try "chmod 755 Calculator"
Right. That's all folks.
I found a good lecture after posting this!
http://www.eng.hawaii.edu/Tutor/Make/1-4.html
Random Linux Commands
chown
chmod XXX
ls -all - list the entire directory and files information
rm
rmdir
apt-get install
apt-get update, - update the existing repository list specified in /etc/apt/sources.list
apt-cache search
GIT Repository
1. git clone
e.g. git://scarlet.aura.cs.cmu.edu/openisr.git
2. git push
e.g. ssh://aarontwc@scarlet.aura.cs.cmu.edu/~aarontwc/openisr.git master
http://davitenio.wordpress.com/2008/10/08/synchronize-git-repositories-between-deskop-and-laptop/
3. git add . - this command adds the existing files in the correct directory to be commited. Basically, it specifies the files to be committed into GIT.
4. git commit -m "message to commit", (instead of just typing git commit, having the -m parameter, allows you to put meaningful text messages to commit, so that its easier for you to track your changes later.
5. git show - this command allow you to see the list of commits make, when and why
6. git pull - this command pulls the latest updates to your local repository.
Kernal.org has a comprehensive guide on GIT.
VIM Editor
1. There are different modes in this editor. To get into editing mode, we need to hit "i", (which is the equivalent of insertion. To escape from editing mode after we are done, we need to hit the 'ESC" key which will then bring us to the main prompt.
2. It allows us to do stuffs faster here in he main prompt, for example, by typing "d" on a line, it allows us to remove the entire line.
3. To save, type, "ZZ" (Shift + Z + Z) or use ":x" (Colon + x + ENTER), this qill automatically save and quit. To quit, go outside insertion mode (press ESC), and then type "ZQ" (Shift + Z + Q) or ":q!" (Colon + q + ! + ENTER). The program will quit without saving.
4. To do more complete stuffs like after being able to recover from a lost SSH connection, look under the area of a swap file. When we try to access the file, it will say something like the file already exist. do you want to edit, recover, delete, quit or abort.
Try the following steps to recover the files or do side by side comparion of iles
1. hit "r" when it asked what you want to do (to recover)
2. :sav! /tmp/%
3. :vs
4. :diffthis
5, CTRL + W + I
6. :bp
7. e (to edit anyway)
8. :diffthis (finds the difference between the two files side by side)
Right that should be all you ever need to know about VIM for basic usage.
Java Problems
Today while coding in java, I ran into two problems.
1. My controls are dynamically generated during runtime. i.e. I have a JTextPane (txtPane) and JButton (btnGenerateRandomNum). Say for example, when btnComment is clicked, I want to paste a randomly generated number into that particulat txtPane. (there are like 20 txtPane each with its own JButton). The question is, on receiving an event from JButton how do I actually go back to the correct txtPane and display the generated random number?
a. first of all you need to create a public list of Jpanels generated
private ArrayList panelList = new ArrayList();
b. add actionCommand with a counter, counter will serve as a unique identifier to the button generated by the java codes. Add this button to the panel and store the panel into the list.
btn.setActionCommand("annotate"+counter);
panel.add(btn);
panelList.add(panel);
c. under actionPerformed method, check that the command received starts with annotate, if it starts, obtain the button ID, based on that, we can obtain the panelList by index. Cast that into the control type you want, in this case, JTextPane, we specify that we want the first component in the JPanel by specifying the index as zero.
if (command.substring(0,8).equals("annotate")) {
int buttonID = Integer.parseInt(command.substring(8))
JPanel tmpPanel = (JPanel) panelList.get(buttonID);
JTextPane tmpArea = (JTextPane) tmpPanel.getComponent(0);
tmpArea.setText= "Yes Success!";
}
The three steps above, allowed us to very simply access controls that were dynamically generated by storing it in an arrayList and getting it back, setting values to it.
[edited, 23rd september]
2. I placed these generated controls into a panel then into a container (with scrollpane). I set the container layout to be BoxLayout. So whenever i click the button "new", a new Panel is inserted into the bottom of the container. This function works perfectly. But it dynamically resizes, i.e. since the height of the container is 500, by pushing the button, it will show 2 panels in correct sizes, by the time i reach the 3rd panel, the panels are resized automatically smaller. (it is trying to fit the size of the container)The question is how do i actually do something like this so that the panel don't resize itself? I tried flowlayout but it does not work correctly (the panel does not appear). I am not sure if there are any layout that I didn't know that works how i need it to - basically to display things from top to bottom (vertically) and don't resize it. Just like how a normal row is added in a table using PHP.
verContainer.setLayout(new BoxLayout(verContainer, BoxLayout.Y_AXIS));
verContainer.add("panel" + counter, inputPanel);
verContainer.setPreferredSize(new Dimension(500,200* counter));
Basically, to prevent dynamic resizing due to the container size, I increase the container size at the same time so that the box layout works perfectly without resizing.