Amiga C

21. Bölüm

Cenker Özkurt

C severler Amiga başına! Bu ayki konumuz, CLI ekranı üzerinde çalışmamızı sağlayan Screen fonksiyonları.

Bildiğiniz gibi, Amiga'da WorkBench disketini ya da herhangi bir çalışma disketimizi taktığımızda karşımıza çıkan ilk şey, AmigaDOS'un CLI ekranıdır. işte Screen fonksiyonları da bu ekran üzerindeki yazı yazma, ekran silme gibi işlemleri yapmamızı sağlayan fonksiyonları kapsıyor. Fakat bu fonksiyonlar C compiler disketinin -lc ya da -lc32 kütüphaneleri içerisinde mevcut değil. Bu nedenle compiler işlemleri sırasında link ederken Screen fonksiyonları içerisinden -ls32 kütüphanesini seçmeliyiz. Aksi takdirde compiler Screen fonksiyonlarını tanıyamaz.

CLI (Command Line Input) aynı zamanda Amiga dos komutlarının icra edildiği pencereyi oluşturuyor. Bildiğiniz gibi bu ekrandan herhangi bir programı da çalıştırmak mümkün. CLI ekranına aynı zamanda 'consol' ekranı da deniyor. Bu nedenle Screen fonksiyonları aynı zamanda 'consol' ekranı üzerinde çalışıyor. Sonradan açacağınız consol ekranı üzerinde de Screen fonksiyonları işlemlerini yapmak mümkün. Consol penceresi örneklerini daha önceki sayılarımızda öğrenmiştik.

Daha önce de söylediğim gibi, CLI ekranı aynı zamanda Dos komutlarını ve hazır programları kullanmamızı sağlıyor. Bildiğiniz gibi, Amiga'da Utility programları dediğimiz yardımcı programlar mevcut. Tahmin ediyorum siz de en azından bir Xcopy, Diskmaster gibi programları kullanıyorsunuzdur. İşte bu tür programlar için bir menü oluşturmak Screen fonksiyonları ile mümkün. Bu nedenle, ben bir örnek program da bu ayki yazımız için hazırladım.

Şimdi gelelim Screen fonksiyonlarının kullanımlarına ve açıklamalarına:
scr_bs(): Bu fonksiyon, aktif ekran pozisyonunu (kursor) bir karakter geri almak için kullanılır.
scr_tab(): Kursor pozisyonunu tab uzunluğu kadar ileri taşır.
scr_lf(): Kursor pozisyonunu bir satır aşağı alır. Eğer satır sonuysa bütün ekranı bir satır yukarı kaydırır.
scr_cursup(): Kursor pozisyonunu bir satır yukarı alır. Bu sırada kolon pozisyonunu değiştirmez.
scr_cursrt(): Kursor pozisyonunu bir karakter sağa taşır. Eğer sağda karakter varsa, bu karakteri silmez.
scr_clear(): Ekranı siler ve kursor pozisyonunu sol üst köşeye taşır (home).
scr_home(): Kursor pozisyonunu home noktasına yani sol üst köşeye taşır.
scr_curs(lin,col): Kursor pozisyonunu verilen kolon ve satırı numarasına getirir.
scr_eol(): Kursor pozisyonundan o satırın sonuna kadar olan karakterleri siler.
scr_linsert(): Kursor pozisyonunun bulunduğu noktaya bir satır boşluk yerleştirir.
str_ldelete(): Kursor pozisyonundan bir karakter siler.
scr_cinsert(): Kursor pozisyonuna bir karakter boşluk yerleştirir ve bu pozisyondan sonraki karakterleri ileri atar.
scr_cdelete(): Kursor pozisyonundan bir karakter siler ve diğer karakterleri bir geri alarak arayı doldurur.

/* Programming by Cenker OZKURT */ 
/* Amiga Dünyası */

#include <stdio.h> 

main()
{
   char a[50]; 
   int lin,col,max;

   strcpy(a,"Amiga Dunyasi");
   lin=10;
   col=10;
   max=strlen(a); 
new_print(a,lin,col,max);
   return(0); 
}

new_print(a,lin,col,max) 
char a[50];
int lin,col,max;
{
   int i;

   for(i=max;i>=0;i--) {
	scr_curs(lin,col); 
printf("%c\n",a[i]"}; 
	scr_cursup(); 
	scr_cinsert(); 
	Delay(1);
   }
   printf("\n");
}
Bu örnek ile, CLI penceresi üzerindeki verilen bir pozisyona herhangi bir diziyi yazdırmamız mümkün.

Şimdi programıızı bir inceleyelim.

#include <stdio.h>
satırı ile, standart input/output fonksiyonlarını ve makrolarını compiler tanıyor. Kullandığımız Delay() fonksiyonu da bu dosya içerisinde tanınıyor. Daha sonra..
char a[50]; 
int lin,col,max;
strcpy(a,"Amiga Dunyasi");
satırları ile, kullanacağımız değişkenleri belirtiyoruz. Burada 'a' değişkeni, ekrana yazacağımız diziyi saklıyor. 'a' değişkenine yazdıracağımız 'Amiga Dünyası' dizisini, strcpy() fonksiyonu ile kopyalıyoruz. 'a' değişkeninin, char tipinde olduğunu unutmamalıyız.

Diğer değişkenlerden 'lin' ve 'col', yazacağımız pozisyonu belirliyor. 'lin' satır, 'col' kolon pozisyonunu saklıyor. 'max' değişkeni ise yazılacak olan dizinin byte olarak uzunluğunu içeriyor. Burada dizinin uzunluğunu,

max=strlen(a);
satırındaki strlen() fonksiyonu ile öğreniyoruz. Daha sonra kendi hazırlamış olduğumuz new_print() alt fonksiyonuna sıçrıyor ve bu fonksiyonun işlevinin icrasından sonra da return() fonksiyonu ile programımızdan hatasız olarak çıktığımızı belirtiyoruz.
new_print(a,lin,col,max); 
  return(0);
new_print() fonksiyonu, daha önce de söylediğim gibi ekranın verilen pozisyonuna istediğimiz diziyi kaydırarak yazdırmamızı sağlıyor. Bu fonksiyonun istediği değerleri, daha önce değişkenler vasıtasıyla hazırlayabileceğimiz gibi, doğrudan fonksiyonu çağırırken de verebiliriz, Biz bu örneğimizde fonksiyonun istediği değerleri değişkenler vasıtasıyla belirledik. Burada fonksiyon ilk parametre olarak diziyi, daha sonra da satır, kolon ve maksimum uzunluk parametre değerlerini istemektedir. Bu nedenle gerekli parametreleri fonksiyonun doğru çalışması için sırasıyla vermeliyiz.

Sıra geldi bu fonksiyonun çalışmasına.

new__print(a,lin,col,max) 
char a[50]; 
int lin,col,max;
{
...
}
Fonksiyonun (ya da rutinin) genel yapısı yukarıda yazılı olduğu gibidir. Rutinimizin parametreleri 'a', 'lin', 'col' ve 'max' olarak tekrar tanımlanmaktadır. Fonksiyon konularımızdan da hatırlayabileceğiniz gibi, fonksiyonun kullandığı değişken isimleri diğer değişken isimleri ile aynı olabilir. Bizim bu fonksiyonu çağırırken kullandığımız değişken isimlerinde olduğu gibi. Bu noktada dikkat edilmesi gereken, gelen değişken tiplerinin tekrar aynı tipte olmasıdır. Aksi takdirde fonksiyon doğru çalışmaz.

Fonksiyonun iç kısımlarında ise ilk olarak 'i' değişkeni integer alarak döngüde kullanılmak üzere tanımlanıyor. Daha sonra 'for' komutu ile döngümüz 'max' değişkeninden 0'a kadar sürüyor. Burada döngüyü 'max' değişkeninden başlatmamızın sebebi, dizimizin son karakterden itibaren yazılmaya başlamasından doğuyor. Sonraki satırlarda,

scr_curs(lin,col);
printf("%c\n",a[i]);
scr_curs() fonksiyonu ile yazılacak karakterin pozisyonunu belirliyoruz. Buradaki 'lin' ve 'col' değişkenlerinin değerlerini daha önceden belirlediğimizi unutmayın. Sonra da printf() ile o noktaya dizi içerisindeki 'i' indisinde bulunan karakterimizi yerleştiriyoruz. Dikkat ettiyseniz, printf() içerisinde "%c" yanında bir de "\n" return kontrol karakter komutunu ekledik. Bunu eklememizdeki sebep, scr_curs() fonksiyonu return işleminden sonra işlemini yerine getiriyor olması.
scr_cursup(); 
scr_cinsert(); 
Delay(1);
satırlarında, scr_cursup() ile kursor pozisyon göstergecini bir satır yukarı alıyor ve scr_cinsert() fonksiyonu ile de bu satıra bir boş karakter yerleştiriyoruz. Delay() ile bir süre bekledikten sonra aynı şekilde dizi sonuna kadar döngü sürüyor ve programdan çıkıyoruz.

Bu örneğimizin üzerinde çalışarak daha da geliştirebilirsiniz.

Sıra geldi ikinci örneğimize. Bu örneğimiz ile istediğiniz Utility programlarını bir diskette topladıktan sonra, disketinizdeki programları aşağıda vermiş olduğum program vasıtasıyla menüden çağırabilirsiniz. Şimdi örneğimize bir göz atalım.

/* Programming by Cenker OZKURT */ 
/* Amiga Dünyası */

#include <stdio.h> 
#include <exec/types.h>

UBYTE *key=0xbfec01;

char *a[] = {"Utility 1",0}; /* Buradaki isimleri disketteki */ 
char *b[] = {"Utility 2",0}; /* isimler ile değiştirmeyi */ 
char *c[] = {"Utility 3",0}; /* unutmayın. Mesela Utilily 1 */ 
char *d[] = {"Utility 4".0}; /* yerine XcopyPro yazabilirsiniz */ 
char *e[] = {"Utility 5",0}; 
char *f[] = {"Utility 6",0};

char text[30];

main()
{
 menu(); 
 while(1) { 
  switch(*key) { 
   case 95: scr_clear();
	sprintf(text,"%s is Loading!..",a[0]); 
	new_print(text,0,0,strlen(text));
	fexecv(a[0],a);
	menu();
	break; 
   case 93: scr_clear();
	sprintf(text,"%s is Loading!..",b[0]);
	new_print(text,0,0,strlen(text));
	fexecv(b[0],b);
	menu();
	break; 
   case 91: scr_clear();
	sprintf(text,"%s is Loading!..",c[0]);
	new_print(text,0,0,strlen(text));
	fexecv(c[0],c);
	menu();
	break; 
   case 89: scr_clear();
	sprintf(text,"%s is Loading!..",d[0]);
	new_print(text,0.0.strlen(text));
	fexecv(d[0],d);
	menu();
	break; 
   case 87: scr_clear();
	sprintf(text,"%s is Loading!..",e[0]);
	new_print(text,0,0,strlen(text));
	fexecv(e[0],e);
	menu();
	break; 
   case 85: scr_clear();
	sprintf(text,"%s is Loading!..",f[0]);
	new_print(text,0,0,strlen(text));
	fexecv(f[0],f);
	menu();
	break; 
   case 77: scr_clear();
	   exit(0);
  }
 }
}

new_print(a,lin,col,max) 
char a[50];
int lin,col,max;
{ 
  int i;

  for(i=max;i>=0;i--) 
    (scr_curs(lin,col); 
    printf("%c\n",a[i]);
    scr_cursup();
    scr_cinsert();
    Delay(1);
 } 
 printf("\n");
}

menu()
{
  scr_clear();
  strcpy(text," Utility Disk");
  new_print(text,8,30,strlen(text));
  strcpy(text,"F1 -> Utility l"); 
new_print(text,10,30,strlen(text));
  strcpy(text,"F2 -> Utility 2"); 
new_print(text,11,30,strlen(text));
  strcpy(text,"F3 -> Utility 3");
new_print(text,12,30,strlen(text));
  strcpy(text,"F4 -> Utility 4");
new_print(text,13,30,strlen(text));
  strcpy(text,"F5 -> Utility 5"); 
new_print(text,l4,30,strlen(text));
  strcpy(text,"F6 -> Utility 6"); 
new_print(text,15,30,strlen(text));
  strcpy(text,"F10 -> Quit");
new_print(text,16,29,strlen(text));
}
Programı yazdıktan sonra, Aztec V3.6 ile compile ederken:
CC +L prog.c 
Link ederken:
LN prog.o -ls32 -lc32
yazmalıyız. -ls32 Screen fonksiyonlarının bulunduğu kütüphaneyi içeriyor. Şimdi programımızı incelemeye başlayabiliriz.

İlk satırlarda gerekli include dosyaları işleniyor. Sonraki satırlarda global olarak tanımlanan değişkenlerimiz var. Bunlar.

UBYTE *key=0xbfec01;

char *a[] = {"Utility 1",0};
char *b[] = {"Utility 2",0};
....
olarak tanımlandı, 'key' değişkenimizi pointer değişken olarak tanımlıyoruz ve bu sırada da adresini biz hex olarak 'bfec01' olarak veriyoruz. Bundan böyle '*key' bize bu adresin byte olarak değerini verecektir. Vermiş olduğumuz adres ise basmış olduğumuz herhangi bir tuşun hardware olarak değerini gösterir. Bu değerler ASCII standartında olmadığı için, herhangi bir tuşun değerini önceden bilmemiz gerekir. Programımızda '95' sayısı F1 tuşuna karşılık geliyor. Diğer tuşları ise aşağıda vermiş olduğum kısa program vasıtasıyla öğrenebilirsiniz.
#include <exec/types.h>

main()
{
  UBYTE *key=0xbfec01;

  while(1) {
    printf("%d\n",*key);
  }
}
Ctrl-C ile programdan çıkabilirsiniz.

Ana programımızın diğer satırlarında a,b,..f'ye kadar disketten yükleyeceğimiz programların isimlerinin saklandığı değişkenleri tanımlıyoruz. Bu isimlerin disketteki isimler olmasına dikkat edin. Aksi takdirde disketinizdeki program icra edilmez.

char text[30], bizim geçici buffer değişkenimizi belirtiyor. Bu değişken vasıtasıyla daha önce vermiş olduğum new_print() fonksiyonuna yazılacak olan dizi gönderiliyor.

Ana main() içerisinde program çalışmaya başlıyor. İlk olarak menu() rutinine sıçrayarak menü ekranımızı hazırlıyoruz. Burada ekrana gelen, yüklenecek olan program isimleri disketteki isimlerden farktı olabilir. Bu nedenle, mesela buraya bir de versiyon numarasını ekleyebilirsiniz.

Daha sonra while(1) ile sonsuz döngüye giriyor ve switch ile de *key değişkenini kontrol ederek tuş ayrımını yapıyoruz. Basılan tuşa göre de ekran temizleniyor, yüklenecek olan programın ismi yazılıyor ve disketteki program,

fexecv(a[0],a);
satırı ile çalışmaya başlıyor. Yüklenmiş olan utility programdan çıktıktan sonra da tekrar menü hazırlanıyor ve fonksiyon tuşlarından birine basılması için bekleniyor.

Programımızın genel açıklaması bu kadar. Bu programı istediğiniz gibi de düzenleyerek daha değişik menüler oluşturmanız oldukça kolay.

Evet, bu ayki program kargaşamız da burada sona eriyor. Gelecek ay yine Amiga C'de buluşmak üzere hepinize bol C Vitaminli günler dilerim...!