17. Bölüm
Cenker Özkurt
Bu ay, geçen ay kaldığımız Buffer'lı olamayan input/output tipi dosyalama rutinlerine devam edeceğiz. Dosyalama işlemleri bittikten sonra, bu ayki ikinci konumuz Amiga'da Screen açılımı ve bazı grafik komutlarının kullanımı. Şimdi kaldığımız yerden devam edelim.
C dili UNIX sisteminde geliştirildiği için, bu sırada ikinci bir input/output sistemi de yaratılmıştı. Bu sisteme buffer'lı olamayan input/output sistemi deniliyor ve ANSI standardına göre tamamen farklı makine diline daha yakın rutinler kullanılıyor. Bu sistemde buffer düzenlemesini, programcı olarak sizin yapmanız gerekmektedir. Unix tipi fonksiyonlar şunlardır:
Fonksiyon İşlevi read() Bir buffer dolusu data okur. write() Bir buffer dolusu data'yı yazar. open() Diskte dosya açar. close() Diskte mevcut datayı kapatır. lseek() Belirtilen byte'ı dosyada arayarak bulur. unlink() İstenilen dosyayı siler.Makina koduna daha yakın yani alçak seviyedeki bu sistemde FILE tipi dosya pointeri olmadığından, onun yerine dosya tarifi int ile yapılmaktadır. Bir dosya açmak için;
int fp; fp=open(dosya adı, mod);yazılır. Burada mod; 0, 1, 2 değerlerini alabilmektedir. Bunlar da sırasıyla oku, yaz ve oku/yaz anlamına gelir. Dosyayı kapatmak içinse,
close(fp);fonksiyonu kullanılır. Eğer open() ile yeni bir dosya açma imkanı yoksa creat() fonksiyonu kullanılır. Kullanım şekli open() ile aynıdır. Dosya açıldıktan sonra write ile dosyaya birşeyler yazmak mümkün:
write(fp,buf,length);Burada fp file pointer'ını, buf yazılacak olan hafıza bloğunun başlangıç adresini, length ise yazılacak olan verinin uzunluğunu belirtiyor. read() fonksiyonu da aynı formda fakat diskten veri okumak için kullanılıyor.
unlink() fonksiyonu, diskten bir dosyayı silmede kullanılır. lseek() fonsiyonu ANSI standartındaki fseek() fonksiyonuna benzer şekilde çalışır.
lseek(fp,offset,origin);Burada offset dosyanın bulunduğu yeri byte cinsinden tesbit eder. Bunun için de, origin parametresine bakar. Origin parametresi 0, 1 ya da 2 olabilir. 0, dosya başı; 1 , o andaki pozisyon; 2, dosya sonunu belirtir.
Aşağıdaki örnek program diskten herhangi bir dosyayı siler. Sileceğimiz dosya ismini main() içerisinden alıyoruz.
main(argc, argv)
int argc;
char *argv[];
{
int a;
if(argc!=2) return();
a=unlink(argv[1]);
if(a!=-1) {
printf("%s dosyası silindi!\n",argv[1]);
} else {
printf("dosya silinemedi\n");
}
}
Buffer'sız input/output işlemleri bu kadar. Buraya kadar anlattığımız dosyalama işlemlerini Amiga rahatlıkla kullanabilirsiniz. Fakat bunların dışında, yalnız Amiga'da kullanılan input/output fonksiyonları da mevcut. Bu fonksiyonlar Amiga'nın 'dos.library'si içerisinde mevcut. Amiga programcılarının hemen hepsi tarafından kullanılan bu rutinler, Amiga'nın sistem rutinleridir. Assembler dahil her dilde bu rutinleri kullanabilirsiniz.
Şimdi Amiga'daki dos.library rutinlerine bakalım. Bu rutinleri kullanmadan önce dos.library'yi açmamız gerekiyor; çünkü kullanacağımız rutinler bu library içerisinde.
Sistem, Buffer'lı olarak çalışıyor ve makine dilinde hazırlanmış. Bu nedenle oldukça hızlı. Komutlar ANSI veya UNIX'teki rutinlerin kullanımıyla hemen hemen aynı.
dos.library'yi açtıktan sonra file pointerini şöyle tanımlıyoruz:
struct FileHandle *file;Buradaki FileHandle yapısı C disketinizdeki include file'ları arasında, dos.h içerisinde tanımlanıyor. Bu nedenle programımızın başına bir de '#include <libraries/dos.h>' cümlesini eklemeliyiz.
Bu sistemin kullandığı fonksiyonların bazıları şunlar:
Fonsiyon İşlevi Open() Dosya açar. Close() Dosyayı kapar. Write() Buffer dolusu bilgiyi yazar. Read() Buffer dolusu bilgiyi okur. Seek() Dosya pozisyon göstergecini ayarlar.Fonksiyonların hemen hepsi ANSI ve UNIX sistemindeki rutinlerin aynısı. Dikkat ettiyseniz, sistem komutlarının baş harfleri büyük olarak kullanılmış. Siz de aynı şekilde yazmaya dikkat edin. Şimdi aşağıdaki örnek programı inceleyelim:
#include <stdio.h>
#include <libraries/dos.h>
struct DosBase * DosBase;
struct FileHandle *file;
main()
{
DosBase=OpenLibrary("dos.library",0);
if(DosBase==NULL) {
printf("dos.library açılamadı!.\n");
return(1);
}
fiIe=Open("deneme",MODE_NEWFILE);
if(file==NULL) {
printf("Dosya açılamadı.\n");
CloseLibrary(DosBase);
return(1);
}
Write(file,"0123456789",10);
Close(file);
CloseLibrary(DosBase);
return(0);
}
Programda, ilk olarak include file'larımızı yazıyoruz.
#include <stdio.h> #include <libraries/dos.h>Burada <stdio.h> içerisinde çokça kullandığımız macrolar ve fonksiyonlar, <libraries/dos.h> içerisinde ise DosBase ve FileHandle yapıları ayrıca dosyalama işlemlerinde kullanılan macrolar tanımlanıyor.
struct DosBase *DosBase; struct FileHandle *file;dos.library rutinlerini kullanmak için, DosBase library pointerini ve dosya pointerini tanımlıyoruz.
DosBase=OpenLibrary("dos.library",0);
Bu satırda dos.library'yi açıyoruz ve daha sonra açılıp açılmadığını kontrol ederek eğer açılmadıysa programdan çıkıyoruz. Burada dos.library yerine DOSNAME macrosunu da kullanabilirsiniz. Bu macroların diğerlerini <librares/dos.h> içerinde bulabilirsiniz.
file=Open("deneme",MODE_NEWFILE);
Burada da 'deneme' ismi altında yeni bir dosya açıyoruz. Open() içerisindeki MODE_NEWFILE macrosu, bize açılacak olan file'ın yeni bir file olduğunu belirtiyor. Tabii ki bu, Open() fonksiyonunun mod parametresi oluyor. Eğer eski bir file üzerinde işlem yapacaksak, MODE_OLDFILE macrosunu kullanmalıyız.
Daha sonra, aynı şekilde dosyanın açılıp açılmadığını kontrol ederek eğer açılmadıysa programdan çıkıyoruz.
Write(file,"0123456789",10);satırında ise, 10 karakterlik bir diziyi 'deneme' dosyasına yazıyor ve;
Close(file); CloseLibrary(DosBase);ile dosyayı ve dos.library'yi kapıyoruz. Diğer Read() ve Seek() fonksiyonlarını da aynı şekilde bu program içerisinde kullanabilirsiniz.
Örnek programımız ve input/output işlemleri burada sona eriyor. Böylece Amiga'da kullanabileceğimiz bütün dosyalama işlemlerini de öğrenmiş bulunuyoruz.
Artık Amiga'da grafik işlemlerine girebiliriz. Bu ay ilk olarak Amiga'da Screen (ekran) açılımını öğreneceğiz. Şimdi örnek programımızı vererek konuya girelim;
#include <stdio.h>
#include <graphics/gfx.h>
#include <intuition/intuition.h>
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Screen *scr;
struct RastPort *rp;
struct NewScreen nw={
0,0,320,200,4,0,1,NULL,CUSTOMSCREEN,NULL,NULL,NULL,NULL };
main()
{
IntuitionBase=OpenLibrary ("intuition.library",0);
if(IntuitionBase==NULL) {
printf("intuitionbase error!\n");
return(1);
}
GfxBase=OpenLibrary ("graphics.library", 0);
if(GfxBase==NULL) {
printf("gfxbase error!\n");
CloseLibrary(IntuitionBase);
return(1);
}
scr=OpenScreen(&nw);
if(scr==NULL) {
printf("screen error!\n");
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
return(1);
}
rp=&(scr->RastPort);
Move(rp,100,100);
Text(rp,"Amiga Dünyası",13);
Delay(100);
CloseScreen(scr);
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
return(0);
}
Buradaki örneğimizle, Amiga'da bir screen açıyoruz ve Text() grafik komutu sayesinde de 'Amiga Dünyası' yazı dizisini, Move() komutu ile ekranın 100'e 100'lük koordinatına yerleştiriyoruz. Programımızın yaptığı iş kısaca böyle. Bu ekranı açtıktan sonra, siz de ekranınızı istediğiniz gibi kullanabilirsiniz. Şimdi programımızı daha derinlemesine inceleyelim:
#include <stdio.h> #include <graphics/gfx.h> #include <intuition/intuition.h>ile grafik ve intuition için gerekli olan yapılar ve macrolar tanımlanarak program derlenmeye hazırlanıyor. Daha sonra,
struct GfxBase *GfxBase; struct IntuitionBase *IntuitionBase;satırları ile GfxBase ve IntuitionBase sistem yapıları bir pointer olarak tanımlanıyor. Burada dikkat edilecek husus; GfxBase ve IntuitionBase yapıları pointer olarak tanımlanırken, farklı bir isim kullanılmaması. Aksi takdirde derleyici grafik ve intuition kullanan rutinleri ana programa bağlarken (link sırasında), hata gösterecektir. Bu pointerler sistemin standart yapılarıdır ve değiştirilemezler.
Bir sonraki satırlarda ise;
struct Screen *scr; struct RastPort *rp;bulunmaktadır. scr, bizim ekran açıldıktan sonra kullanacağımız, ekranla ilgili bilgileri saklayan yapı değişkenimizdir. Bu değişken vasıtasıyle ekranın hangi hafıza bloğunda bulunduğunu, mouse pozisyonunu ve buna benzer birçok bilgiyi kontrol edebiliriz. Daha sonra,
struct NewScreen nw={
0,0,320,200,4,0,1,NULL,CUSTOMSCREEN,NULL,NULL,NULL,NULL };
satırları bulunmaktadır. NewScreen, bizim yeni ekranımızın yapı değişkenidir ve bu da Amiga sisteminin standart yapılarındandır. Biz bu yapı yardımıyla ekran özelliklerimizi sisteme bildiririz ve ekranımızı açarız. Buradaki 'nw' değişkeni de, bu yapı özelliğinde tanımlanarak ilk değerleri alır. İlk değerlerimiz sırasıyla; x başlangıç (LeftEdge), y başlangıç (TopEdge), genişlik (Width), uzunluk (Height), bitplane sayısı (Depth), kalem rengi (DetailPen), kağıt rengi (BlockPen), ekran görünümü (ViewMode), ekran tipi (Type), ekranın kullanacağı font ismi (TextAttr), ekran ismi (DefaultTitle), ekranda kullanılacak olan kutular (Gadgets) ve ekranın plane düzeni (bitmap) dir. Bu yapı da, gfx.h içinde aşağıdaki gibi tanımlanmaktadır.
struct NewScreen
{
SHORT LeftEdge,TopEdge,Width,Height,Depth;
UBYTE DetailPen,BlockPen;
USHORT ViewModes;
USHORT Type;
struct TextAttr *Font;
UBYTE *DefaultTitle;
struct Gadget *Gadgets;
struct BitMap *CustomBitMap;
};
Bir sonraki satırlarda ise, ana programa başlanır. GfxBase ve IntuitionBase library'leri açılarak, eğer bir hata yoksa;
scr=OpenScreen(&nw);satırına gelinir. 'nw' bizim ekranla ile bilgilerin saklandığı yapımızdır. OpenScreen() fonksiyonu ile bu ekran açılır ve 'scr' değişkenine, ekranla ilgili bilgilerin saklandığı yapı adresi aktarılır. Eğer ekranımız açılamazsa, NULL macrosuyla geri döner ve library'ler kapanarak programdan çıkılır. Ekran açıldıktan sonra ise,
rp=&(scr->RastPort);ile açılan ekranımızın hafıza yapısıyla ile bilgilerin saklandığı RastPort değişkeninin adresi, 'rp' değişkenine aktarılır. Ve daha sonra,
Move(rp,100,100); Text(rp,"Amiga Dünyası",13);ile logomuz yazılır. Delay() ile bir süre bekledikten sonra, açılan ekranımız ve library'ler kapanarak, programdan hatasız olarak çıktığımızı belirten;
return(0);satırı ile programımızdan çıkarız.
Programımızı bir kez daha inceledikten ve yazılımını da kavradıktan sonra artık deneyebilirsiniz. Derleme işlemleri ise kısaca (Aztec C V3.6a için!):
cc +1 prog.c in prog.o -lc32şeklindedir. Editör yardımıyla programımızı yazın ve siz de üzerinde oynayın.
Şimdilik bu kadar. Gelecek ay yeni örneklerle buluşmak üzere hepinize iyi çalışmalar dilerim.