Amiga C

15. Bölüm

Cenker Özkurt

Hepinize selam. Bu ayki yazıma Hakan arkadaşımızın sorularını cevaplayarak başlamak istiyorum. Soruların cevapları belki sizleri de bazı konularda aydınlatabilir. Çünkü sorular C öğrenmek isteyen herkesin genelde sorduğu türden.

İlk soru şu; AmigaBasic'teki INKEY$ fonksiyonu gibi ekrana yazmadan klavyeden bilgi alma fonksiyonunun ne olduğu.

AmigaBasic'teki INKEY$ gibi bir fonksiyon Amiga C'de mevcut değil. Buna benzer gets() ya da getchar() gibi fonksiyonlar mevcut. Fakat tabii, bu fonksiyonlar tam olarak INKEY$ fonksiyonunun yapmış olduğu işi yapmaz. Çünkü bu fonksiyonlarda bir karakter girildikten sonra, RETURN tuşuna basmak gerekir. Aynı zamanda yazılan karakter de ekranda görülür.

Fakat bu fonksiyona benzer bir fonksiyon hazırlanabilir. Bunu yapmak için gerekli olan ilk şey, klavyeyi kontrol eden registerin adresini okumak. Ben size bu registerin adres değerini vererek, sizin için ilk adımı atabilirim. Bundan sonrası size kalmış.

Bu registerin değeri $bfec01 adresidir. Size bir ipucu daha: Değişkeni şöyle tanımlayabilirsiniz. Böylece gelen değer pozitif bir tamsayı olmuş olur.

unsigned char *key=0xbfec01;
Artık bundan sonrası *key değişkeninin değerini okumak. Gerçi size de bundan başka fazla iş düşmüyor.

Gelelim ikinci soruya; arkadaşımız program içerisinde Basic'teki Color ve Palette ifadelerinin benzerinin nasıl kullanılacağını sormuş. Bu soruların cevabını öğrenmeden önce, C'de bilmeniz, gereken bazı noktalar var. İlk olarak, Basic'teki gibi bir Window (pencere) ve Screen (ekran) açmayı öğrenmemiz gerekiyor. Çünkü bu komutlar daha çok bu ekran ve pencereleri ilgilendiriyor. Fakat bilginiz olsun diye bir iki örnek verebilirim.

Başlangıçta ekranın kaç renkli olacağını Screen açarken belirliyoruz. Daha sonra seçmek istediğimiz kalem rengini;

SetAPen(rp,renkkodu)
kağıt rengini;
SetBPen(rp,renkkodu)
kazı modunu ise;
SetDrMd(rp,JAM2)
olarak belirtiyoruz. Gerçi bunları Screen açarken de belirtebiliriz ama, sonradan bir değişiklik gerekirse yukarıdaki fonksiyonları kullanmalıyız.

Eğer renklerin paletleriyle oynamak istersek;

SetRGB4(vp,renkkodu,kırmızıdeğer,yeşildeğer,mavideğer)
bilgilerini vermemiz gerekiyor. Buradaki kırmızı, yeşil ve mavi (RGB) değerleri 0-15 arası olabiliyor. Bu sayede renk kodu altındaki rengin değerini 4096'lık bir paletten seçebiliyoruz. Vp ise, ViewPort adresini belirtiyor. ViewPort adresi, ekrana renk düzeninin saklandığı adresi veriyor. ViewPort adresini screen açtıktan sonra screen structer'ından alıyoruz.

Gördüğünüz gibi, bu noktada bilmemiz gereken daha başka şeyler var. Fakat ben gene de bilginiz olsun diyerek vermek istedim. Bu konularla ilgili örnekleri daha sonraki sayılarda bulabilirsiniz.

Üçüncü soruda ise, C'de grafik komutlarının neler olduğu ve bunların nasıl kullanılacağı.

Az önce anlattığım gibi, ilk olarak bir screen ve window açmalısınız. Yukarıda vermiş olduğum komutlar da zaten grafik komutlarına giriyor. Bundan başka Amiga C'de oldukça fazla grafik komutu mevcut. Mesela; Move(), Draw(), ReadPixel(), Flood(), Clip(), ScrollRaster(), BltBitMapRastPort() gibi. Bu örnekleri çoğaltmak mümkün. Fakat bunları yazmak ve açıklamak birkaç sayı sürebilir. Bu nedenle yeri geldikçe öğreneceğiz. Zaten şöyle bir durum mevcut: Bir komutu kullanmasını öğrendikten sonra diğerlerini kullanmak çorap söküğü gibi gelir. Önemli olan hangi komutun ne iş yaptığını ve hangi parametreleri istediğini öğrenmek. Bu bilgilerin tamamını da Amiga kitap kutüphanesinde bulabilirsiniz. Bu kitapların bazıları şunlar: Amiga Rom Kernel Reference Manual ya da Amiga Hardware & Devices Reference Manual. Bunlar zaten Amiga'da program yazmayı öğrenmek isteyen herkeste bulunması gereken kitaplar.

Dördüncü soruda Basic'teki Ptab ve Line komutlarının benzerlerinin C'deki karşılığı. Şunu söylemem gerekir ki; Basic'teki her komutun C'de bir karşılığı olamayabilir. Onun için ilk olarak bu komutların ne iş yaptığını tesbit edip, benzerini C'de bir alt routine olarak hazırlamak.

Son soruda ise program çıktılarının (grafik, yazı gibi) printer'dan nasıl çıkarılacağı ve Türkçe fontların nasıl hazırlanacağı.

Bazı printer işlemleri için, eğer yazı yazdıracaksanız normal bir dosya açar gibi, dosya ismi yerine "PRT:" yazmalısınız. Bunun sonucunda dosya'ya yazmak istediğiniz her bilgi printer'e gidecektir. Eğer grafik çizdirecekseniz, bu şimdilik uzun iş. Fakat size bu iş için kullanabileceğiniz routine'i gelecek sayılarda vereceğim.

C'de Türkçe font kullanmak için, önceden bir font editörü yardımıyla herhangi bir boyda Türkçe fontları hazırlamalısınız. Bunu kaydektikten sonra, C'den "OpenDiskFont();" fonksiyonu yardımıyla, bu fontu kullanabilirsiniz.

Artık bu ayki ilk örneğimize geçebiliriz. Bu ay ilk olarak Workbench üstüne basit olarak bir window'un nasıl açıldığını ve bu window'dan nasıl bilgi okunduğunu göreceğiz.

/* Basit Window Tekniği */

#define ESC 27

main()
{
int handle;
char *c;

handle = open("CON:0/0/200/50/Window",0,0);

if(handle != -1)
{
do
{
read(handle,c,1);
printf("Karakter %c", *c);
} while(*c !=ESC);
close(handle);
}
}
/* Program sonu */
Programımızı ilk satırdan açıklamaya başlayabiliriz.
#define ESC 27
komutu ile, Escape tuşunun kod değerini bir macro değişken olarak ESC macrosuna atıyoruz. "main()" ile ana program başlıyor ve,
int handle;
char *c;
ile, değişken tanımlamalarını yapıyoruz. Burada 'handle' window structure'nın yapı adresini saklıyoruz. 'handle', aynı zamanda bize window'un açılıp açılmadığını gösteriyor.
read(handle,c,1);
printf("Karakter %c", *c);
Burada ise, read() fonksiyonu ile window'dan tek karakterlik bir giriş bekleniyor ve daha sonra printf(); ile WorkBench ekranına yazılıyor.

"read()" fonksiyonu, burada yeni. Bu fonksiyon, aynı zamanda dosyalarla ilgili işlemlerde de çok karşımıza çıkacak.

while(*c != ESC);
ile, gelen karakterin ESC olup olmadığına bakıyoruz. Eğer değilse program sona eriyor.

Bu giriş örneğinden sonra, şimdi de oldukça faydalı olan bir kopya (copy) programını inceleyelim. Buradaki örnekte programınızı compile ettikten sonra, çalıştırırken program isminizin yanına iki tane ayrı parametre gireceksiniz. Birinci parametre, kopya edilecek olan dosyanın; ikincisi ise, yeni dosyanın ismini belirleyecek. Eğer parametreleri eksik ya da fazla girerseniz, programımız giriş hatası verecektir.

Dikkat ederseniz, ana programımızın isminden sonra iki parametre giriyoruz. Bu parametreleri Amiga sistemimiz bize yolluyor. Yollanan değerleri programı inceleyerek anlamaya çalışalım;

/* Kopya programı */ 
#include <stdio.h>

main(argc,argv)
int argc;
char *argv[];
{
if(argc != 3)
{
printf('Giriş hatası!"); 
printf("Kaynak Hedef");
}
else
copy(argv[1],argv[2]);
}
copy(fromfile,tofile)
char *fromfile, *tofile;
{
FILE *input, *output, *fopen();
register long counter=0;
register int c;

if(!(input=fopen(fromfile,"r")))
{
printf("%s dosyası okumaya açılamadı!",fromfile);
return0;
}
if(!(output=fopen(tofile,"w")))
{
printf("%s dosyası yazmaya açılamadı!", tofile);
fclose(input);
return 0;
}

while((c=fgetc(input)) != EOF)
{
fputc(c,output); 
counter++;
}

fclose(input); 
fclose(output); 
printf("%ld Byte kopyalandı!",counter);
}

/* Program sonu */
Programımızı açıklamaya başlayalım;
#include <stdio.h>
ile, stdio.h include dosyası gözden geçiriliyor ve fopen(), fclose(), fgetc(), fputc() tanımlamaları yapılıyor.
main(argc,argv)
int argc;
char *argv[];
Burada görüldüğü gibi, main() fonksiyonu içinde 'argc' ve 'argv' değişkenleri bulunuyor. Bu değişkenlerden 'argc', bize program isminden sonra verilen parametre sayısını, 'argv' ise, parametrelerin kendisini veriyor. Bir örnek vermek gerekirse;
copy prog.c ram:prog2.c
copy program ismimiz ve ilk parametre, prog.c ikinci parametre, ram:prog2.c son parametreyi belirliyor. Parametre sayımız ise üç oluyor. Daha sonraki satırlarda ise;
{
printf('Giriş hatası!"); 
printf("Kaynak Hedef");
}
else
copy(argv[1],argv[2]);
parametre sayısını kontrol ediyoruz. Eğer 3'ten farklıysa, program sona eriyor. Yani 'Giriş hatası!' vererek çıkıyor. Değilse copy() routine'nimize sıçrıyorum. Burada 'argv[l]' ilk parametrenin, 'argv[2]' ise ikinci parametrenin kendisini veriyor. Bu değerler ile copy() işleniyor.
copy(fromfile,tofile)
char *fromfile, *tofile;
ile, kaynak (fromfile) ve hedef (tofile) değişkenleri copy() routine içine atanıyor.
FILE *input, *output, *fopen();
register long counter=0;
register int c;
input(), output(), fopen() değişkenleri, FILE olarak tanımlanıyor. Burada FILE dosya yapısının değişken türünü oluşturuyor.
if(!(input=fopen(fromfile,"r")))
{
printf("%s dosyası okumaya açılamadı!",fromfile);
return0;
}
fopen() ile, kaynak dosya (fromfile) "r" parametresi ile okumaya açılıyor. Eğer açılamazsa, hata vererek ana programa geri dönülüyor, 'input' değişkeni, bu dosyanın structure yapı adresini saklıyor,
if(!(output = fopen(tofile,"w")))
{
printf("%s dosyası yazmaya açılamadı!", tofile);
fclose(input);
return 0;
}
Aynı şekilde hedef dosya, (tofile) "w" parametresi ile yazmaya açılıyor. Aksi taktirde ana programa geri dönülüyor. Burada da aynı şekilde output değişkeni dosyanın structure yapı adresi saklıyor.
while((c=fgetc(input)) != EOF)
{
fputc(c,output); 
counter++;
}
Burada ise fgetc() fonksiyonu ile bir karakteri bir değer kaynak dosyadan 'c' değişkenine kopyalanıyor. Eğer dosya sonuna ulaşılırsa, EOF mesajı nedeniyle döngüden çıkılıyor.
fclose(input); 
fclose(output); 
printf("%ld Byte kopyalandı!",counter);
fclose() fonksiyonları, açılan 'input' ve 'output' dosyalarını kapıyor. Daha sonra printf() ile kopyalanan byte ya da karakter sayısı ekrana yazılarak programdan çıkılıyor.

Bu ayki yazımız da burada sona eriyor. Yukarıdaki program, dosya işlemleriyle yapmış olduğumuz ilk programı oluşturuyor. Bu örnekleri sizler çoğaltabilirsiniz. Şimdilik bu kadar. Gelecek ay yeni örnek programlarla buluşmak üzere hoşçakalın!...